1 //! Utilities for manipulating and extracting information from `rustc_ast::ast`.
3 //! - The `eq_foobar` functions test for semantic equality but ignores `NodeId`s and `Span`s.
5 #![allow(clippy::similar_names, clippy::wildcard_imports, clippy::enum_glob_use)]
7 use crate::{both, over}
;
8 use if_chain
::if_chain
;
10 use rustc_ast
::{self as ast, *}
;
11 use rustc_span
::symbol
::Ident
;
15 pub use ident_iter
::IdentIter
;
17 pub fn is_useless_with_eq_exprs(kind
: BinOpKind
) -> bool
{
21 Sub
| Div
| Eq
| Lt
| Le
| Gt
| Ge
| Ne
| And
| Or
| BitXor
| BitAnd
| BitOr
25 /// Checks if each element in the first slice is contained within the latter as per `eq_fn`.
26 pub fn unordered_over
<X
>(left
: &[X
], right
: &[X
], mut eq_fn
: impl FnMut(&X
, &X
) -> bool
) -> bool
{
27 left
.len() == right
.len() && left
.iter().all(|l
| right
.iter().any(|r
| eq_fn(l
, r
)))
30 pub fn eq_id(l
: Ident
, r
: Ident
) -> bool
{
34 pub fn eq_pat(l
: &Pat
, r
: &Pat
) -> bool
{
36 match (&l
.kind
, &r
.kind
) {
37 (Paren(l
), _
) => eq_pat(l
, r
),
38 (_
, Paren(r
)) => eq_pat(l
, r
),
39 (Wild
, Wild
) | (Rest
, Rest
) => true,
40 (Lit(l
), Lit(r
)) => eq_expr(l
, r
),
41 (Ident(b1
, i1
, s1
), Ident(b2
, i2
, s2
)) => b1
== b2
&& eq_id(*i1
, *i2
) && both(s1
, s2
, |l
, r
| eq_pat(l
, r
)),
42 (Range(lf
, lt
, le
), Range(rf
, rt
, re
)) => {
43 eq_expr_opt(lf
, rf
) && eq_expr_opt(lt
, rt
) && eq_range_end(&le
.node
, &re
.node
)
46 | (Ref(l
, Mutability
::Not
), Ref(r
, Mutability
::Not
))
47 | (Ref(l
, Mutability
::Mut
), Ref(r
, Mutability
::Mut
)) => eq_pat(l
, r
),
48 (Tuple(l
), Tuple(r
)) | (Slice(l
), Slice(r
)) => over(l
, r
, |l
, r
| eq_pat(l
, r
)),
49 (Path(lq
, lp
), Path(rq
, rp
)) => both(lq
, rq
, |l
, r
| eq_qself(l
, r
)) && eq_path(lp
, rp
),
50 (TupleStruct(lp
, lfs
), TupleStruct(rp
, rfs
)) => eq_path(lp
, rp
) && over(lfs
, rfs
, |l
, r
| eq_pat(l
, r
)),
51 (Struct(lp
, lfs
, lr
), Struct(rp
, rfs
, rr
)) => {
52 lr
== rr
&& eq_path(lp
, rp
) && unordered_over(lfs
, rfs
, |lf
, rf
| eq_field_pat(lf
, rf
))
54 (Or(ls
), Or(rs
)) => unordered_over(ls
, rs
, |l
, r
| eq_pat(l
, r
)),
55 (MacCall(l
), MacCall(r
)) => eq_mac_call(l
, r
),
60 pub fn eq_range_end(l
: &RangeEnd
, r
: &RangeEnd
) -> bool
{
62 (RangeEnd
::Excluded
, RangeEnd
::Excluded
) => true,
63 (RangeEnd
::Included(l
), RangeEnd
::Included(r
)) => {
64 matches
!(l
, RangeSyntax
::DotDotEq
) == matches
!(r
, RangeSyntax
::DotDotEq
)
70 pub fn eq_field_pat(l
: &PatField
, r
: &PatField
) -> bool
{
71 l
.is_placeholder
== r
.is_placeholder
72 && eq_id(l
.ident
, r
.ident
)
73 && eq_pat(&l
.pat
, &r
.pat
)
74 && over(&l
.attrs
, &r
.attrs
, |l
, r
| eq_attr(l
, r
))
77 pub fn eq_qself(l
: &QSelf
, r
: &QSelf
) -> bool
{
78 l
.position
== r
.position
&& eq_ty(&l
.ty
, &r
.ty
)
81 pub fn eq_path(l
: &Path
, r
: &Path
) -> bool
{
82 over(&l
.segments
, &r
.segments
, |l
, r
| eq_path_seg(l
, r
))
85 pub fn eq_path_seg(l
: &PathSegment
, r
: &PathSegment
) -> bool
{
86 eq_id(l
.ident
, r
.ident
) && both(&l
.args
, &r
.args
, |l
, r
| eq_generic_args(l
, r
))
89 pub fn eq_generic_args(l
: &GenericArgs
, r
: &GenericArgs
) -> bool
{
91 (GenericArgs
::AngleBracketed(l
), GenericArgs
::AngleBracketed(r
)) => {
92 over(&l
.args
, &r
.args
, |l
, r
| eq_angle_arg(l
, r
))
94 (GenericArgs
::Parenthesized(l
), GenericArgs
::Parenthesized(r
)) => {
95 over(&l
.inputs
, &r
.inputs
, |l
, r
| eq_ty(l
, r
)) && eq_fn_ret_ty(&l
.output
, &r
.output
)
101 pub fn eq_angle_arg(l
: &AngleBracketedArg
, r
: &AngleBracketedArg
) -> bool
{
103 (AngleBracketedArg
::Arg(l
), AngleBracketedArg
::Arg(r
)) => eq_generic_arg(l
, r
),
104 (AngleBracketedArg
::Constraint(l
), AngleBracketedArg
::Constraint(r
)) => eq_assoc_constraint(l
, r
),
109 pub fn eq_generic_arg(l
: &GenericArg
, r
: &GenericArg
) -> bool
{
111 (GenericArg
::Lifetime(l
), GenericArg
::Lifetime(r
)) => eq_id(l
.ident
, r
.ident
),
112 (GenericArg
::Type(l
), GenericArg
::Type(r
)) => eq_ty(l
, r
),
113 (GenericArg
::Const(l
), GenericArg
::Const(r
)) => eq_expr(&l
.value
, &r
.value
),
118 pub fn eq_expr_opt(l
: &Option
<P
<Expr
>>, r
: &Option
<P
<Expr
>>) -> bool
{
119 both(l
, r
, |l
, r
| eq_expr(l
, r
))
122 pub fn eq_struct_rest(l
: &StructRest
, r
: &StructRest
) -> bool
{
124 (StructRest
::Base(lb
), StructRest
::Base(rb
)) => eq_expr(lb
, rb
),
125 (StructRest
::Rest(_
), StructRest
::Rest(_
)) | (StructRest
::None
, StructRest
::None
) => true,
130 pub fn eq_expr(l
: &Expr
, r
: &Expr
) -> bool
{
132 if !over(&l
.attrs
, &r
.attrs
, |l
, r
| eq_attr(l
, r
)) {
135 match (&l
.kind
, &r
.kind
) {
136 (Paren(l
), _
) => eq_expr(l
, r
),
137 (_
, Paren(r
)) => eq_expr(l
, r
),
139 (Box(l
), Box(r
)) | (Try(l
), Try(r
)) | (Await(l
), Await(r
)) => eq_expr(l
, r
),
140 (Array(l
), Array(r
)) | (Tup(l
), Tup(r
)) => over(l
, r
, |l
, r
| eq_expr(l
, r
)),
141 (Repeat(le
, ls
), Repeat(re
, rs
)) => eq_expr(le
, re
) && eq_expr(&ls
.value
, &rs
.value
),
142 (Call(lc
, la
), Call(rc
, ra
)) => eq_expr(lc
, rc
) && over(la
, ra
, |l
, r
| eq_expr(l
, r
)),
143 (MethodCall(lc
, la
, _
), MethodCall(rc
, ra
, _
)) => eq_path_seg(lc
, rc
) && over(la
, ra
, |l
, r
| eq_expr(l
, r
)),
144 (Binary(lo
, ll
, lr
), Binary(ro
, rl
, rr
)) => lo
.node
== ro
.node
&& eq_expr(ll
, rl
) && eq_expr(lr
, rr
),
145 (Unary(lo
, l
), Unary(ro
, r
)) => mem
::discriminant(lo
) == mem
::discriminant(ro
) && eq_expr(l
, r
),
146 (Lit(l
), Lit(r
)) => l
.kind
== r
.kind
,
147 (Cast(l
, lt
), Cast(r
, rt
)) | (Type(l
, lt
), Type(r
, rt
)) => eq_expr(l
, r
) && eq_ty(lt
, rt
),
148 (Let(lp
, le
), Let(rp
, re
)) => eq_pat(lp
, rp
) && eq_expr(le
, re
),
149 (If(lc
, lt
, le
), If(rc
, rt
, re
)) => eq_expr(lc
, rc
) && eq_block(lt
, rt
) && eq_expr_opt(le
, re
),
150 (While(lc
, lt
, ll
), While(rc
, rt
, rl
)) => eq_label(ll
, rl
) && eq_expr(lc
, rc
) && eq_block(lt
, rt
),
151 (ForLoop(lp
, li
, lt
, ll
), ForLoop(rp
, ri
, rt
, rl
)) => {
152 eq_label(ll
, rl
) && eq_pat(lp
, rp
) && eq_expr(li
, ri
) && eq_block(lt
, rt
)
154 (Loop(lt
, ll
), Loop(rt
, rl
)) => eq_label(ll
, rl
) && eq_block(lt
, rt
),
155 (Block(lb
, ll
), Block(rb
, rl
)) => eq_label(ll
, rl
) && eq_block(lb
, rb
),
156 (TryBlock(l
), TryBlock(r
)) => eq_block(l
, r
),
157 (Yield(l
), Yield(r
)) | (Ret(l
), Ret(r
)) => eq_expr_opt(l
, r
),
158 (Break(ll
, le
), Break(rl
, re
)) => eq_label(ll
, rl
) && eq_expr_opt(le
, re
),
159 (Continue(ll
), Continue(rl
)) => eq_label(ll
, rl
),
160 (Assign(l1
, l2
, _
), Assign(r1
, r2
, _
)) | (Index(l1
, l2
), Index(r1
, r2
)) => eq_expr(l1
, r1
) && eq_expr(l2
, r2
),
161 (AssignOp(lo
, lp
, lv
), AssignOp(ro
, rp
, rv
)) => lo
.node
== ro
.node
&& eq_expr(lp
, rp
) && eq_expr(lv
, rv
),
162 (Field(lp
, lf
), Field(rp
, rf
)) => eq_id(*lf
, *rf
) && eq_expr(lp
, rp
),
163 (Match(ls
, la
), Match(rs
, ra
)) => eq_expr(ls
, rs
) && over(la
, ra
, |l
, r
| eq_arm(l
, r
)),
164 (Closure(lc
, la
, lm
, lf
, lb
, _
), Closure(rc
, ra
, rm
, rf
, rb
, _
)) => {
165 lc
== rc
&& la
.is_async() == ra
.is_async() && lm
== rm
&& eq_fn_decl(lf
, rf
) && eq_expr(lb
, rb
)
167 (Async(lc
, _
, lb
), Async(rc
, _
, rb
)) => lc
== rc
&& eq_block(lb
, rb
),
168 (Range(lf
, lt
, ll
), Range(rf
, rt
, rl
)) => ll
== rl
&& eq_expr_opt(lf
, rf
) && eq_expr_opt(lt
, rt
),
169 (AddrOf(lbk
, lm
, le
), AddrOf(rbk
, rm
, re
)) => lbk
== rbk
&& lm
== rm
&& eq_expr(le
, re
),
170 (Path(lq
, lp
), Path(rq
, rp
)) => both(lq
, rq
, |l
, r
| eq_qself(l
, r
)) && eq_path(lp
, rp
),
171 (MacCall(l
), MacCall(r
)) => eq_mac_call(l
, r
),
172 (Struct(lse
), Struct(rse
)) => {
173 eq_path(&lse
.path
, &rse
.path
)
174 && eq_struct_rest(&lse
.rest
, &rse
.rest
)
175 && unordered_over(&lse
.fields
, &rse
.fields
, |l
, r
| eq_field(l
, r
))
181 pub fn eq_field(l
: &ExprField
, r
: &ExprField
) -> bool
{
182 l
.is_placeholder
== r
.is_placeholder
183 && eq_id(l
.ident
, r
.ident
)
184 && eq_expr(&l
.expr
, &r
.expr
)
185 && over(&l
.attrs
, &r
.attrs
, |l
, r
| eq_attr(l
, r
))
188 pub fn eq_arm(l
: &Arm
, r
: &Arm
) -> bool
{
189 l
.is_placeholder
== r
.is_placeholder
190 && eq_pat(&l
.pat
, &r
.pat
)
191 && eq_expr(&l
.body
, &r
.body
)
192 && eq_expr_opt(&l
.guard
, &r
.guard
)
193 && over(&l
.attrs
, &r
.attrs
, |l
, r
| eq_attr(l
, r
))
196 pub fn eq_label(l
: &Option
<Label
>, r
: &Option
<Label
>) -> bool
{
197 both(l
, r
, |l
, r
| eq_id(l
.ident
, r
.ident
))
200 pub fn eq_block(l
: &Block
, r
: &Block
) -> bool
{
201 l
.rules
== r
.rules
&& over(&l
.stmts
, &r
.stmts
, |l
, r
| eq_stmt(l
, r
))
204 pub fn eq_stmt(l
: &Stmt
, r
: &Stmt
) -> bool
{
206 match (&l
.kind
, &r
.kind
) {
207 (Local(l
), Local(r
)) => {
208 eq_pat(&l
.pat
, &r
.pat
)
209 && both(&l
.ty
, &r
.ty
, |l
, r
| eq_ty(l
, r
))
210 && eq_expr_opt(&l
.init
, &r
.init
)
211 && over(&l
.attrs
, &r
.attrs
, |l
, r
| eq_attr(l
, r
))
213 (Item(l
), Item(r
)) => eq_item(l
, r
, eq_item_kind
),
214 (Expr(l
), Expr(r
)) | (Semi(l
), Semi(r
)) => eq_expr(l
, r
),
215 (Empty
, Empty
) => true,
216 (MacCall(l
), MacCall(r
)) => {
217 l
.style
== r
.style
&& eq_mac_call(&l
.mac
, &r
.mac
) && over(&l
.attrs
, &r
.attrs
, |l
, r
| eq_attr(l
, r
))
223 pub fn eq_item
<K
>(l
: &Item
<K
>, r
: &Item
<K
>, mut eq_kind
: impl FnMut(&K
, &K
) -> bool
) -> bool
{
224 eq_id(l
.ident
, r
.ident
)
225 && over(&l
.attrs
, &r
.attrs
, |l
, r
| eq_attr(l
, r
))
226 && eq_vis(&l
.vis
, &r
.vis
)
227 && eq_kind(&l
.kind
, &r
.kind
)
230 pub fn eq_item_kind(l
: &ItemKind
, r
: &ItemKind
) -> bool
{
233 (ExternCrate(l
), ExternCrate(r
)) => l
== r
,
234 (Use(l
), Use(r
)) => eq_use_tree(l
, r
),
235 (Static(lt
, lm
, le
), Static(rt
, rm
, re
)) => lm
== rm
&& eq_ty(lt
, rt
) && eq_expr_opt(le
, re
),
236 (Const(ld
, lt
, le
), Const(rd
, rt
, re
)) => eq_defaultness(*ld
, *rd
) && eq_ty(lt
, rt
) && eq_expr_opt(le
, re
),
237 (Fn(box FnKind(ld
, lf
, lg
, lb
)), Fn(box FnKind(rd
, rf
, rg
, rb
))) => {
238 eq_defaultness(*ld
, *rd
) && eq_fn_sig(lf
, rf
) && eq_generics(lg
, rg
) && both(lb
, rb
, |l
, r
| eq_block(l
, r
))
240 (Mod(lu
, lmk
), Mod(ru
, rmk
)) => {
242 && match (lmk
, rmk
) {
243 (ModKind
::Loaded(litems
, linline
, _
), ModKind
::Loaded(ritems
, rinline
, _
)) => {
244 linline
== rinline
&& over(litems
, ritems
, |l
, r
| eq_item(l
, r
, eq_item_kind
))
246 (ModKind
::Unloaded
, ModKind
::Unloaded
) => true,
250 (ForeignMod(l
), ForeignMod(r
)) => {
251 both(&l
.abi
, &r
.abi
, |l
, r
| eq_str_lit(l
, r
))
252 && over(&l
.items
, &r
.items
, |l
, r
| eq_item(l
, r
, eq_foreign_item_kind
))
254 (TyAlias(box TyAliasKind(ld
, lg
, lb
, lt
)), TyAlias(box TyAliasKind(rd
, rg
, rb
, rt
))) => {
255 eq_defaultness(*ld
, *rd
)
256 && eq_generics(lg
, rg
)
257 && over(lb
, rb
, |l
, r
| eq_generic_bound(l
, r
))
258 && both(lt
, rt
, |l
, r
| eq_ty(l
, r
))
260 (Enum(le
, lg
), Enum(re
, rg
)) => {
261 over(&le
.variants
, &re
.variants
, |l
, r
| eq_variant(l
, r
)) && eq_generics(lg
, rg
)
263 (Struct(lv
, lg
), Struct(rv
, rg
)) | (Union(lv
, lg
), Union(rv
, rg
)) => {
264 eq_variant_data(lv
, rv
) && eq_generics(lg
, rg
)
266 (Trait(box TraitKind(la
, lu
, lg
, lb
, li
)), Trait(box TraitKind(ra
, ru
, rg
, rb
, ri
))) => {
268 && matches
!(lu
, Unsafe
::No
) == matches
!(ru
, Unsafe
::No
)
269 && eq_generics(lg
, rg
)
270 && over(lb
, rb
, |l
, r
| eq_generic_bound(l
, r
))
271 && over(li
, ri
, |l
, r
| eq_item(l
, r
, eq_assoc_item_kind
))
273 (TraitAlias(lg
, lb
), TraitAlias(rg
, rb
)) => eq_generics(lg
, rg
) && over(lb
, rb
, |l
, r
| eq_generic_bound(l
, r
)),
296 matches
!(lu
, Unsafe
::No
) == matches
!(ru
, Unsafe
::No
)
297 && matches
!(lp
, ImplPolarity
::Positive
) == matches
!(rp
, ImplPolarity
::Positive
)
298 && eq_defaultness(*ld
, *rd
)
299 && matches
!(lc
, ast
::Const
::No
) == matches
!(rc
, ast
::Const
::No
)
300 && eq_generics(lg
, rg
)
301 && both(lot
, rot
, |l
, r
| eq_path(&l
.path
, &r
.path
))
303 && over(li
, ri
, |l
, r
| eq_item(l
, r
, eq_assoc_item_kind
))
305 (MacCall(l
), MacCall(r
)) => eq_mac_call(l
, r
),
306 (MacroDef(l
), MacroDef(r
)) => l
.macro_rules
== r
.macro_rules
&& eq_mac_args(&l
.body
, &r
.body
),
311 pub fn eq_foreign_item_kind(l
: &ForeignItemKind
, r
: &ForeignItemKind
) -> bool
{
312 use ForeignItemKind
::*;
314 (Static(lt
, lm
, le
), Static(rt
, rm
, re
)) => lm
== rm
&& eq_ty(lt
, rt
) && eq_expr_opt(le
, re
),
315 (Fn(box FnKind(ld
, lf
, lg
, lb
)), Fn(box FnKind(rd
, rf
, rg
, rb
))) => {
316 eq_defaultness(*ld
, *rd
) && eq_fn_sig(lf
, rf
) && eq_generics(lg
, rg
) && both(lb
, rb
, |l
, r
| eq_block(l
, r
))
318 (TyAlias(box TyAliasKind(ld
, lg
, lb
, lt
)), TyAlias(box TyAliasKind(rd
, rg
, rb
, rt
))) => {
319 eq_defaultness(*ld
, *rd
)
320 && eq_generics(lg
, rg
)
321 && over(lb
, rb
, |l
, r
| eq_generic_bound(l
, r
))
322 && both(lt
, rt
, |l
, r
| eq_ty(l
, r
))
324 (MacCall(l
), MacCall(r
)) => eq_mac_call(l
, r
),
329 pub fn eq_assoc_item_kind(l
: &AssocItemKind
, r
: &AssocItemKind
) -> bool
{
330 use AssocItemKind
::*;
332 (Const(ld
, lt
, le
), Const(rd
, rt
, re
)) => eq_defaultness(*ld
, *rd
) && eq_ty(lt
, rt
) && eq_expr_opt(le
, re
),
333 (Fn(box FnKind(ld
, lf
, lg
, lb
)), Fn(box FnKind(rd
, rf
, rg
, rb
))) => {
334 eq_defaultness(*ld
, *rd
) && eq_fn_sig(lf
, rf
) && eq_generics(lg
, rg
) && both(lb
, rb
, |l
, r
| eq_block(l
, r
))
336 (TyAlias(box TyAliasKind(ld
, lg
, lb
, lt
)), TyAlias(box TyAliasKind(rd
, rg
, rb
, rt
))) => {
337 eq_defaultness(*ld
, *rd
)
338 && eq_generics(lg
, rg
)
339 && over(lb
, rb
, |l
, r
| eq_generic_bound(l
, r
))
340 && both(lt
, rt
, |l
, r
| eq_ty(l
, r
))
342 (MacCall(l
), MacCall(r
)) => eq_mac_call(l
, r
),
347 pub fn eq_variant(l
: &Variant
, r
: &Variant
) -> bool
{
348 l
.is_placeholder
== r
.is_placeholder
349 && over(&l
.attrs
, &r
.attrs
, |l
, r
| eq_attr(l
, r
))
350 && eq_vis(&l
.vis
, &r
.vis
)
351 && eq_id(l
.ident
, r
.ident
)
352 && eq_variant_data(&l
.data
, &r
.data
)
353 && both(&l
.disr_expr
, &r
.disr_expr
, |l
, r
| eq_expr(&l
.value
, &r
.value
))
356 pub fn eq_variant_data(l
: &VariantData
, r
: &VariantData
) -> bool
{
359 (Unit(_
), Unit(_
)) => true,
360 (Struct(l
, _
), Struct(r
, _
)) | (Tuple(l
, _
), Tuple(r
, _
)) => over(l
, r
, |l
, r
| eq_struct_field(l
, r
)),
365 pub fn eq_struct_field(l
: &FieldDef
, r
: &FieldDef
) -> bool
{
366 l
.is_placeholder
== r
.is_placeholder
367 && over(&l
.attrs
, &r
.attrs
, |l
, r
| eq_attr(l
, r
))
368 && eq_vis(&l
.vis
, &r
.vis
)
369 && both(&l
.ident
, &r
.ident
, |l
, r
| eq_id(*l
, *r
))
370 && eq_ty(&l
.ty
, &r
.ty
)
373 pub fn eq_fn_sig(l
: &FnSig
, r
: &FnSig
) -> bool
{
374 eq_fn_decl(&l
.decl
, &r
.decl
) && eq_fn_header(&l
.header
, &r
.header
)
377 pub fn eq_fn_header(l
: &FnHeader
, r
: &FnHeader
) -> bool
{
378 matches
!(l
.unsafety
, Unsafe
::No
) == matches
!(r
.unsafety
, Unsafe
::No
)
379 && l
.asyncness
.is_async() == r
.asyncness
.is_async()
380 && matches
!(l
.constness
, Const
::No
) == matches
!(r
.constness
, Const
::No
)
381 && eq_ext(&l
.ext
, &r
.ext
)
384 pub fn eq_generics(l
: &Generics
, r
: &Generics
) -> bool
{
385 over(&l
.params
, &r
.params
, |l
, r
| eq_generic_param(l
, r
))
386 && over(&l
.where_clause
.predicates
, &r
.where_clause
.predicates
, |l
, r
| {
387 eq_where_predicate(l
, r
)
391 pub fn eq_where_predicate(l
: &WherePredicate
, r
: &WherePredicate
) -> bool
{
392 use WherePredicate
::*;
394 (BoundPredicate(l
), BoundPredicate(r
)) => {
395 over(&l
.bound_generic_params
, &r
.bound_generic_params
, |l
, r
| {
396 eq_generic_param(l
, r
)
397 }) && eq_ty(&l
.bounded_ty
, &r
.bounded_ty
)
398 && over(&l
.bounds
, &r
.bounds
, |l
, r
| eq_generic_bound(l
, r
))
400 (RegionPredicate(l
), RegionPredicate(r
)) => {
401 eq_id(l
.lifetime
.ident
, r
.lifetime
.ident
) && over(&l
.bounds
, &r
.bounds
, |l
, r
| eq_generic_bound(l
, r
))
403 (EqPredicate(l
), EqPredicate(r
)) => eq_ty(&l
.lhs_ty
, &r
.lhs_ty
) && eq_ty(&l
.rhs_ty
, &r
.rhs_ty
),
408 pub fn eq_use_tree(l
: &UseTree
, r
: &UseTree
) -> bool
{
409 eq_path(&l
.prefix
, &r
.prefix
) && eq_use_tree_kind(&l
.kind
, &r
.kind
)
412 pub fn eq_anon_const(l
: &AnonConst
, r
: &AnonConst
) -> bool
{
413 eq_expr(&l
.value
, &r
.value
)
416 pub fn eq_use_tree_kind(l
: &UseTreeKind
, r
: &UseTreeKind
) -> bool
{
419 (Glob
, Glob
) => true,
420 (Simple(l
, _
, _
), Simple(r
, _
, _
)) => both(l
, r
, |l
, r
| eq_id(*l
, *r
)),
421 (Nested(l
), Nested(r
)) => over(l
, r
, |(l
, _
), (r
, _
)| eq_use_tree(l
, r
)),
426 pub fn eq_defaultness(l
: Defaultness
, r
: Defaultness
) -> bool
{
429 (Defaultness
::Final
, Defaultness
::Final
) | (Defaultness
::Default(_
), Defaultness
::Default(_
))
433 pub fn eq_vis(l
: &Visibility
, r
: &Visibility
) -> bool
{
434 use VisibilityKind
::*;
435 match (&l
.kind
, &r
.kind
) {
436 (Public
, Public
) | (Inherited
, Inherited
) | (Crate(_
), Crate(_
)) => true,
437 (Restricted { path: l, .. }
, Restricted { path: r, .. }
) => eq_path(l
, r
),
442 pub fn eq_fn_decl(l
: &FnDecl
, r
: &FnDecl
) -> bool
{
443 eq_fn_ret_ty(&l
.output
, &r
.output
)
444 && over(&l
.inputs
, &r
.inputs
, |l
, r
| {
445 l
.is_placeholder
== r
.is_placeholder
446 && eq_pat(&l
.pat
, &r
.pat
)
447 && eq_ty(&l
.ty
, &r
.ty
)
448 && over(&l
.attrs
, &r
.attrs
, |l
, r
| eq_attr(l
, r
))
452 pub fn eq_fn_ret_ty(l
: &FnRetTy
, r
: &FnRetTy
) -> bool
{
454 (FnRetTy
::Default(_
), FnRetTy
::Default(_
)) => true,
455 (FnRetTy
::Ty(l
), FnRetTy
::Ty(r
)) => eq_ty(l
, r
),
460 pub fn eq_ty(l
: &Ty
, r
: &Ty
) -> bool
{
462 match (&l
.kind
, &r
.kind
) {
463 (Paren(l
), _
) => eq_ty(l
, r
),
464 (_
, Paren(r
)) => eq_ty(l
, r
),
465 (Never
, Never
) | (Infer
, Infer
) | (ImplicitSelf
, ImplicitSelf
) | (Err
, Err
) | (CVarArgs
, CVarArgs
) => true,
466 (Slice(l
), Slice(r
)) => eq_ty(l
, r
),
467 (Array(le
, ls
), Array(re
, rs
)) => eq_ty(le
, re
) && eq_expr(&ls
.value
, &rs
.value
),
468 (Ptr(l
), Ptr(r
)) => l
.mutbl
== r
.mutbl
&& eq_ty(&l
.ty
, &r
.ty
),
469 (Rptr(ll
, l
), Rptr(rl
, r
)) => {
470 both(ll
, rl
, |l
, r
| eq_id(l
.ident
, r
.ident
)) && l
.mutbl
== r
.mutbl
&& eq_ty(&l
.ty
, &r
.ty
)
472 (BareFn(l
), BareFn(r
)) => {
473 l
.unsafety
== r
.unsafety
474 && eq_ext(&l
.ext
, &r
.ext
)
475 && over(&l
.generic_params
, &r
.generic_params
, |l
, r
| eq_generic_param(l
, r
))
476 && eq_fn_decl(&l
.decl
, &r
.decl
)
478 (Tup(l
), Tup(r
)) => over(l
, r
, |l
, r
| eq_ty(l
, r
)),
479 (Path(lq
, lp
), Path(rq
, rp
)) => both(lq
, rq
, |l
, r
| eq_qself(l
, r
)) && eq_path(lp
, rp
),
480 (TraitObject(lg
, ls
), TraitObject(rg
, rs
)) => ls
== rs
&& over(lg
, rg
, |l
, r
| eq_generic_bound(l
, r
)),
481 (ImplTrait(_
, lg
), ImplTrait(_
, rg
)) => over(lg
, rg
, |l
, r
| eq_generic_bound(l
, r
)),
482 (Typeof(l
), Typeof(r
)) => eq_expr(&l
.value
, &r
.value
),
483 (MacCall(l
), MacCall(r
)) => eq_mac_call(l
, r
),
488 pub fn eq_ext(l
: &Extern
, r
: &Extern
) -> bool
{
491 (None
, None
) | (Implicit
, Implicit
) => true,
492 (Explicit(l
), Explicit(r
)) => eq_str_lit(l
, r
),
497 pub fn eq_str_lit(l
: &StrLit
, r
: &StrLit
) -> bool
{
498 l
.style
== r
.style
&& l
.symbol
== r
.symbol
&& l
.suffix
== r
.suffix
501 pub fn eq_poly_ref_trait(l
: &PolyTraitRef
, r
: &PolyTraitRef
) -> bool
{
502 eq_path(&l
.trait_ref
.path
, &r
.trait_ref
.path
)
503 && over(&l
.bound_generic_params
, &r
.bound_generic_params
, |l
, r
| {
504 eq_generic_param(l
, r
)
508 pub fn eq_generic_param(l
: &GenericParam
, r
: &GenericParam
) -> bool
{
509 use GenericParamKind
::*;
510 l
.is_placeholder
== r
.is_placeholder
511 && eq_id(l
.ident
, r
.ident
)
512 && over(&l
.bounds
, &r
.bounds
, |l
, r
| eq_generic_bound(l
, r
))
513 && match (&l
.kind
, &r
.kind
) {
514 (Lifetime
, Lifetime
) => true,
515 (Type { default: l }
, Type { default: r }
) => both(l
, r
, |l
, r
| eq_ty(l
, r
)),
527 ) => eq_ty(lt
, rt
) && both(ld
, rd
, |ld
, rd
| eq_anon_const(ld
, rd
)),
530 && over(&l
.attrs
, &r
.attrs
, |l
, r
| eq_attr(l
, r
))
533 pub fn eq_generic_bound(l
: &GenericBound
, r
: &GenericBound
) -> bool
{
536 (Trait(ptr1
, tbm1
), Trait(ptr2
, tbm2
)) => tbm1
== tbm2
&& eq_poly_ref_trait(ptr1
, ptr2
),
537 (Outlives(l
), Outlives(r
)) => eq_id(l
.ident
, r
.ident
),
542 pub fn eq_assoc_constraint(l
: &AssocTyConstraint
, r
: &AssocTyConstraint
) -> bool
{
543 use AssocTyConstraintKind
::*;
544 eq_id(l
.ident
, r
.ident
)
545 && match (&l
.kind
, &r
.kind
) {
546 (Equality { ty: l }
, Equality { ty: r }
) => eq_ty(l
, r
),
547 (Bound { bounds: l }
, Bound { bounds: r }
) => over(l
, r
, |l
, r
| eq_generic_bound(l
, r
)),
552 pub fn eq_mac_call(l
: &MacCall
, r
: &MacCall
) -> bool
{
553 eq_path(&l
.path
, &r
.path
) && eq_mac_args(&l
.args
, &r
.args
)
556 pub fn eq_attr(l
: &Attribute
, r
: &Attribute
) -> bool
{
559 && match (&l
.kind
, &r
.kind
) {
560 (DocComment(l1
, l2
), DocComment(r1
, r2
)) => l1
== r1
&& l2
== r2
,
561 (Normal(l
, _
), Normal(r
, _
)) => eq_path(&l
.path
, &r
.path
) && eq_mac_args(&l
.args
, &r
.args
),
566 pub fn eq_mac_args(l
: &MacArgs
, r
: &MacArgs
) -> bool
{
569 (Empty
, Empty
) => true,
570 (Delimited(_
, ld
, lts
), Delimited(_
, rd
, rts
)) => ld
== rd
&& lts
.eq_unspanned(rts
),
571 (Eq(_
, lt
), Eq(_
, rt
)) => lt
.kind
== rt
.kind
,
576 /// Extract args from an assert-like macro.
578 /// Currently working with:
579 /// - `assert_eq!` and `assert_ne!`
580 /// - `debug_assert_eq!` and `debug_assert_ne!`
584 /// `debug_assert_eq!(a, b)` will return Some([a, b])
585 pub fn extract_assert_macro_args(mut expr
: &Expr
) -> Option
<[&Expr
; 2]> {
587 if let ExprKind
::If(_
, ref block
, _
) = expr
.kind
;
588 if let StmtKind
::Semi(ref e
) = block
.stmts
.get(0)?
.kind
;
594 if let ExprKind
::Block(ref block
, _
) = expr
.kind
;
595 if let StmtKind
::Expr(ref expr
) = block
.stmts
.get(0)?
.kind
;
596 if let ExprKind
::Match(ref match_expr
, _
) = expr
.kind
;
597 if let ExprKind
::Tup(ref tup
) = match_expr
.kind
;
598 if let [a
, b
, ..] = tup
.as_slice();
599 if let (&ExprKind
::AddrOf(_
, _
, ref a
), &ExprKind
::AddrOf(_
, _
, ref b
)) = (&a
.kind
, &b
.kind
);
601 return Some([&*a
, &*b
]);