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}
;
9 use rustc_ast
::{self as ast, *}
;
10 use rustc_span
::symbol
::Ident
;
14 pub use ident_iter
::IdentIter
;
16 pub fn is_useless_with_eq_exprs(kind
: BinOpKind
) -> bool
{
20 Sub
| Div
| Eq
| Lt
| Le
| Gt
| Ge
| Ne
| And
| Or
| BitXor
| BitAnd
| BitOr
24 /// Checks if each element in the first slice is contained within the latter as per `eq_fn`.
25 pub fn unordered_over
<X
>(left
: &[X
], right
: &[X
], mut eq_fn
: impl FnMut(&X
, &X
) -> bool
) -> bool
{
26 left
.len() == right
.len() && left
.iter().all(|l
| right
.iter().any(|r
| eq_fn(l
, r
)))
29 pub fn eq_id(l
: Ident
, r
: Ident
) -> bool
{
33 pub fn eq_pat(l
: &Pat
, r
: &Pat
) -> bool
{
35 match (&l
.kind
, &r
.kind
) {
36 (Paren(l
), _
) => eq_pat(l
, r
),
37 (_
, Paren(r
)) => eq_pat(l
, r
),
38 (Wild
, Wild
) | (Rest
, Rest
) => true,
39 (Lit(l
), Lit(r
)) => eq_expr(l
, r
),
40 (Ident(b1
, i1
, s1
), Ident(b2
, i2
, s2
)) => b1
== b2
&& eq_id(*i1
, *i2
) && both(s1
, s2
, |l
, r
| eq_pat(l
, r
)),
41 (Range(lf
, lt
, le
), Range(rf
, rt
, re
)) => {
42 eq_expr_opt(lf
, rf
) && eq_expr_opt(lt
, rt
) && eq_range_end(&le
.node
, &re
.node
)
45 | (Ref(l
, Mutability
::Not
), Ref(r
, Mutability
::Not
))
46 | (Ref(l
, Mutability
::Mut
), Ref(r
, Mutability
::Mut
)) => eq_pat(l
, r
),
47 (Tuple(l
), Tuple(r
)) | (Slice(l
), Slice(r
)) => over(l
, r
, |l
, r
| eq_pat(l
, r
)),
48 (Path(lq
, lp
), Path(rq
, rp
)) => both(lq
, rq
, eq_qself
) && eq_path(lp
, rp
),
49 (TupleStruct(lqself
, lp
, lfs
), TupleStruct(rqself
, rp
, rfs
)) => {
50 eq_maybe_qself(lqself
, rqself
) && eq_path(lp
, rp
) && over(lfs
, rfs
, |l
, r
| eq_pat(l
, r
))
52 (Struct(lqself
, lp
, lfs
, lr
), Struct(rqself
, rp
, rfs
, rr
)) => {
53 lr
== rr
&& eq_maybe_qself(lqself
, rqself
) && eq_path(lp
, rp
) && unordered_over(lfs
, rfs
, eq_field_pat
)
55 (Or(ls
), Or(rs
)) => unordered_over(ls
, rs
, |l
, r
| eq_pat(l
, r
)),
56 (MacCall(l
), MacCall(r
)) => eq_mac_call(l
, r
),
61 pub fn eq_range_end(l
: &RangeEnd
, r
: &RangeEnd
) -> bool
{
63 (RangeEnd
::Excluded
, RangeEnd
::Excluded
) => true,
64 (RangeEnd
::Included(l
), RangeEnd
::Included(r
)) => {
65 matches
!(l
, RangeSyntax
::DotDotEq
) == matches
!(r
, RangeSyntax
::DotDotEq
)
71 pub fn eq_field_pat(l
: &PatField
, r
: &PatField
) -> bool
{
72 l
.is_placeholder
== r
.is_placeholder
73 && eq_id(l
.ident
, r
.ident
)
74 && eq_pat(&l
.pat
, &r
.pat
)
75 && over(&l
.attrs
, &r
.attrs
, eq_attr
)
78 pub fn eq_qself(l
: &P
<QSelf
>, r
: &P
<QSelf
>) -> bool
{
79 l
.position
== r
.position
&& eq_ty(&l
.ty
, &r
.ty
)
82 pub fn eq_maybe_qself(l
: &Option
<P
<QSelf
>>, r
: &Option
<P
<QSelf
>>) -> bool
{
84 (Some(l
), Some(r
)) => eq_qself(l
, r
),
90 pub fn eq_path(l
: &Path
, r
: &Path
) -> bool
{
91 over(&l
.segments
, &r
.segments
, eq_path_seg
)
94 pub fn eq_path_seg(l
: &PathSegment
, r
: &PathSegment
) -> bool
{
95 eq_id(l
.ident
, r
.ident
) && both(&l
.args
, &r
.args
, |l
, r
| eq_generic_args(l
, r
))
98 pub fn eq_generic_args(l
: &GenericArgs
, r
: &GenericArgs
) -> bool
{
100 (GenericArgs
::AngleBracketed(l
), GenericArgs
::AngleBracketed(r
)) => over(&l
.args
, &r
.args
, eq_angle_arg
),
101 (GenericArgs
::Parenthesized(l
), GenericArgs
::Parenthesized(r
)) => {
102 over(&l
.inputs
, &r
.inputs
, |l
, r
| eq_ty(l
, r
)) && eq_fn_ret_ty(&l
.output
, &r
.output
)
108 pub fn eq_angle_arg(l
: &AngleBracketedArg
, r
: &AngleBracketedArg
) -> bool
{
110 (AngleBracketedArg
::Arg(l
), AngleBracketedArg
::Arg(r
)) => eq_generic_arg(l
, r
),
111 (AngleBracketedArg
::Constraint(l
), AngleBracketedArg
::Constraint(r
)) => eq_assoc_constraint(l
, r
),
116 pub fn eq_generic_arg(l
: &GenericArg
, r
: &GenericArg
) -> bool
{
118 (GenericArg
::Lifetime(l
), GenericArg
::Lifetime(r
)) => eq_id(l
.ident
, r
.ident
),
119 (GenericArg
::Type(l
), GenericArg
::Type(r
)) => eq_ty(l
, r
),
120 (GenericArg
::Const(l
), GenericArg
::Const(r
)) => eq_expr(&l
.value
, &r
.value
),
125 pub fn eq_expr_opt(l
: &Option
<P
<Expr
>>, r
: &Option
<P
<Expr
>>) -> bool
{
126 both(l
, r
, |l
, r
| eq_expr(l
, r
))
129 pub fn eq_struct_rest(l
: &StructRest
, r
: &StructRest
) -> bool
{
131 (StructRest
::Base(lb
), StructRest
::Base(rb
)) => eq_expr(lb
, rb
),
132 (StructRest
::Rest(_
), StructRest
::Rest(_
)) | (StructRest
::None
, StructRest
::None
) => true,
137 pub fn eq_expr(l
: &Expr
, r
: &Expr
) -> bool
{
139 if !over(&l
.attrs
, &r
.attrs
, eq_attr
) {
142 match (&l
.kind
, &r
.kind
) {
143 (Paren(l
), _
) => eq_expr(l
, r
),
144 (_
, Paren(r
)) => eq_expr(l
, r
),
146 (Box(l
), Box(r
)) | (Try(l
), Try(r
)) | (Await(l
), Await(r
)) => eq_expr(l
, r
),
147 (Array(l
), Array(r
)) | (Tup(l
), Tup(r
)) => over(l
, r
, |l
, r
| eq_expr(l
, r
)),
148 (Repeat(le
, ls
), Repeat(re
, rs
)) => eq_expr(le
, re
) && eq_expr(&ls
.value
, &rs
.value
),
149 (Call(lc
, la
), Call(rc
, ra
)) => eq_expr(lc
, rc
) && over(la
, ra
, |l
, r
| eq_expr(l
, r
)),
151 MethodCall(box ast
::MethodCall
{
157 MethodCall(box ast
::MethodCall
{
163 ) => eq_path_seg(ls
, rs
) && eq_expr(lr
, rr
) && over(la
, ra
, |l
, r
| eq_expr(l
, r
)),
164 (Binary(lo
, ll
, lr
), Binary(ro
, rl
, rr
)) => lo
.node
== ro
.node
&& eq_expr(ll
, rl
) && eq_expr(lr
, rr
),
165 (Unary(lo
, l
), Unary(ro
, r
)) => mem
::discriminant(lo
) == mem
::discriminant(ro
) && eq_expr(l
, r
),
166 (Lit(l
), Lit(r
)) => l
== r
,
167 (Cast(l
, lt
), Cast(r
, rt
)) | (Type(l
, lt
), Type(r
, rt
)) => eq_expr(l
, r
) && eq_ty(lt
, rt
),
168 (Let(lp
, le
, _
), Let(rp
, re
, _
)) => eq_pat(lp
, rp
) && eq_expr(le
, re
),
169 (If(lc
, lt
, le
), If(rc
, rt
, re
)) => eq_expr(lc
, rc
) && eq_block(lt
, rt
) && eq_expr_opt(le
, re
),
170 (While(lc
, lt
, ll
), While(rc
, rt
, rl
)) => eq_label(ll
, rl
) && eq_expr(lc
, rc
) && eq_block(lt
, rt
),
171 (ForLoop(lp
, li
, lt
, ll
), ForLoop(rp
, ri
, rt
, rl
)) => {
172 eq_label(ll
, rl
) && eq_pat(lp
, rp
) && eq_expr(li
, ri
) && eq_block(lt
, rt
)
174 (Loop(lt
, ll
, _
), Loop(rt
, rl
, _
)) => eq_label(ll
, rl
) && eq_block(lt
, rt
),
175 (Block(lb
, ll
), Block(rb
, rl
)) => eq_label(ll
, rl
) && eq_block(lb
, rb
),
176 (TryBlock(l
), TryBlock(r
)) => eq_block(l
, r
),
177 (Yield(l
), Yield(r
)) | (Ret(l
), Ret(r
)) => eq_expr_opt(l
, r
),
178 (Break(ll
, le
), Break(rl
, re
)) => eq_label(ll
, rl
) && eq_expr_opt(le
, re
),
179 (Continue(ll
), Continue(rl
)) => eq_label(ll
, rl
),
180 (Assign(l1
, l2
, _
), Assign(r1
, r2
, _
)) | (Index(l1
, l2
), Index(r1
, r2
)) => eq_expr(l1
, r1
) && eq_expr(l2
, r2
),
181 (AssignOp(lo
, lp
, lv
), AssignOp(ro
, rp
, rv
)) => lo
.node
== ro
.node
&& eq_expr(lp
, rp
) && eq_expr(lv
, rv
),
182 (Field(lp
, lf
), Field(rp
, rf
)) => eq_id(*lf
, *rf
) && eq_expr(lp
, rp
),
183 (Match(ls
, la
), Match(rs
, ra
)) => eq_expr(ls
, rs
) && over(la
, ra
, eq_arm
),
185 Closure(box ast
::Closure
{
194 Closure(box ast
::Closure
{
204 eq_closure_binder(lb
, rb
)
206 && la
.is_async() == ra
.is_async()
208 && eq_fn_decl(lf
, rf
)
211 (Async(lc
, _
, lb
), Async(rc
, _
, rb
)) => lc
== rc
&& eq_block(lb
, rb
),
212 (Range(lf
, lt
, ll
), Range(rf
, rt
, rl
)) => ll
== rl
&& eq_expr_opt(lf
, rf
) && eq_expr_opt(lt
, rt
),
213 (AddrOf(lbk
, lm
, le
), AddrOf(rbk
, rm
, re
)) => lbk
== rbk
&& lm
== rm
&& eq_expr(le
, re
),
214 (Path(lq
, lp
), Path(rq
, rp
)) => both(lq
, rq
, eq_qself
) && eq_path(lp
, rp
),
215 (MacCall(l
), MacCall(r
)) => eq_mac_call(l
, r
),
216 (Struct(lse
), Struct(rse
)) => {
217 eq_maybe_qself(&lse
.qself
, &rse
.qself
)
218 && eq_path(&lse
.path
, &rse
.path
)
219 && eq_struct_rest(&lse
.rest
, &rse
.rest
)
220 && unordered_over(&lse
.fields
, &rse
.fields
, eq_field
)
226 pub fn eq_field(l
: &ExprField
, r
: &ExprField
) -> bool
{
227 l
.is_placeholder
== r
.is_placeholder
228 && eq_id(l
.ident
, r
.ident
)
229 && eq_expr(&l
.expr
, &r
.expr
)
230 && over(&l
.attrs
, &r
.attrs
, eq_attr
)
233 pub fn eq_arm(l
: &Arm
, r
: &Arm
) -> bool
{
234 l
.is_placeholder
== r
.is_placeholder
235 && eq_pat(&l
.pat
, &r
.pat
)
236 && eq_expr(&l
.body
, &r
.body
)
237 && eq_expr_opt(&l
.guard
, &r
.guard
)
238 && over(&l
.attrs
, &r
.attrs
, eq_attr
)
241 pub fn eq_label(l
: &Option
<Label
>, r
: &Option
<Label
>) -> bool
{
242 both(l
, r
, |l
, r
| eq_id(l
.ident
, r
.ident
))
245 pub fn eq_block(l
: &Block
, r
: &Block
) -> bool
{
246 l
.rules
== r
.rules
&& over(&l
.stmts
, &r
.stmts
, eq_stmt
)
249 pub fn eq_stmt(l
: &Stmt
, r
: &Stmt
) -> bool
{
251 match (&l
.kind
, &r
.kind
) {
252 (Local(l
), Local(r
)) => {
253 eq_pat(&l
.pat
, &r
.pat
)
254 && both(&l
.ty
, &r
.ty
, |l
, r
| eq_ty(l
, r
))
255 && eq_local_kind(&l
.kind
, &r
.kind
)
256 && over(&l
.attrs
, &r
.attrs
, eq_attr
)
258 (Item(l
), Item(r
)) => eq_item(l
, r
, eq_item_kind
),
259 (Expr(l
), Expr(r
)) | (Semi(l
), Semi(r
)) => eq_expr(l
, r
),
260 (Empty
, Empty
) => true,
261 (MacCall(l
), MacCall(r
)) => {
262 l
.style
== r
.style
&& eq_mac_call(&l
.mac
, &r
.mac
) && over(&l
.attrs
, &r
.attrs
, eq_attr
)
268 pub fn eq_local_kind(l
: &LocalKind
, r
: &LocalKind
) -> bool
{
271 (Decl
, Decl
) => true,
272 (Init(l
), Init(r
)) => eq_expr(l
, r
),
273 (InitElse(li
, le
), InitElse(ri
, re
)) => eq_expr(li
, ri
) && eq_block(le
, re
),
278 pub fn eq_item
<K
>(l
: &Item
<K
>, r
: &Item
<K
>, mut eq_kind
: impl FnMut(&K
, &K
) -> bool
) -> bool
{
279 eq_id(l
.ident
, r
.ident
) && over(&l
.attrs
, &r
.attrs
, eq_attr
) && eq_vis(&l
.vis
, &r
.vis
) && eq_kind(&l
.kind
, &r
.kind
)
282 #[expect(clippy::too_many_lines)] // Just a big match statement
283 pub fn eq_item_kind(l
: &ItemKind
, r
: &ItemKind
) -> bool
{
286 (ExternCrate(l
), ExternCrate(r
)) => l
== r
,
287 (Use(l
), Use(r
)) => eq_use_tree(l
, r
),
288 (Static(lt
, lm
, le
), Static(rt
, rm
, re
)) => lm
== rm
&& eq_ty(lt
, rt
) && eq_expr_opt(le
, re
),
289 (Const(ld
, lt
, le
), Const(rd
, rt
, re
)) => eq_defaultness(*ld
, *rd
) && eq_ty(lt
, rt
) && eq_expr_opt(le
, re
),
304 eq_defaultness(*ld
, *rd
) && eq_fn_sig(lf
, rf
) && eq_generics(lg
, rg
) && both(lb
, rb
, |l
, r
| eq_block(l
, r
))
306 (Mod(lu
, lmk
), Mod(ru
, rmk
)) => {
308 && match (lmk
, rmk
) {
309 (ModKind
::Loaded(litems
, linline
, _
), ModKind
::Loaded(ritems
, rinline
, _
)) => {
310 linline
== rinline
&& over(litems
, ritems
, |l
, r
| eq_item(l
, r
, eq_item_kind
))
312 (ModKind
::Unloaded
, ModKind
::Unloaded
) => true,
316 (ForeignMod(l
), ForeignMod(r
)) => {
317 both(&l
.abi
, &r
.abi
, eq_str_lit
) && over(&l
.items
, &r
.items
, |l
, r
| eq_item(l
, r
, eq_foreign_item_kind
))
320 TyAlias(box ast
::TyAlias
{
327 TyAlias(box ast
::TyAlias
{
335 eq_defaultness(*ld
, *rd
)
336 && eq_generics(lg
, rg
)
337 && over(lb
, rb
, eq_generic_bound
)
338 && both(lt
, rt
, |l
, r
| eq_ty(l
, r
))
340 (Enum(le
, lg
), Enum(re
, rg
)) => over(&le
.variants
, &re
.variants
, eq_variant
) && eq_generics(lg
, rg
),
341 (Struct(lv
, lg
), Struct(rv
, rg
)) | (Union(lv
, lg
), Union(rv
, rg
)) => {
342 eq_variant_data(lv
, rv
) && eq_generics(lg
, rg
)
345 Trait(box ast
::Trait
{
352 Trait(box ast
::Trait
{
361 && matches
!(lu
, Unsafe
::No
) == matches
!(ru
, Unsafe
::No
)
362 && eq_generics(lg
, rg
)
363 && over(lb
, rb
, eq_generic_bound
)
364 && over(li
, ri
, |l
, r
| eq_item(l
, r
, eq_assoc_item_kind
))
366 (TraitAlias(lg
, lb
), TraitAlias(rg
, rb
)) => eq_generics(lg
, rg
) && over(lb
, rb
, eq_generic_bound
),
389 matches
!(lu
, Unsafe
::No
) == matches
!(ru
, Unsafe
::No
)
390 && matches
!(lp
, ImplPolarity
::Positive
) == matches
!(rp
, ImplPolarity
::Positive
)
391 && eq_defaultness(*ld
, *rd
)
392 && matches
!(lc
, ast
::Const
::No
) == matches
!(rc
, ast
::Const
::No
)
393 && eq_generics(lg
, rg
)
394 && both(lot
, rot
, |l
, r
| eq_path(&l
.path
, &r
.path
))
396 && over(li
, ri
, |l
, r
| eq_item(l
, r
, eq_assoc_item_kind
))
398 (MacCall(l
), MacCall(r
)) => eq_mac_call(l
, r
),
399 (MacroDef(l
), MacroDef(r
)) => l
.macro_rules
== r
.macro_rules
&& eq_delim_args(&l
.body
, &r
.body
),
404 pub fn eq_foreign_item_kind(l
: &ForeignItemKind
, r
: &ForeignItemKind
) -> bool
{
405 use ForeignItemKind
::*;
407 (Static(lt
, lm
, le
), Static(rt
, rm
, re
)) => lm
== rm
&& eq_ty(lt
, rt
) && eq_expr_opt(le
, re
),
422 eq_defaultness(*ld
, *rd
) && eq_fn_sig(lf
, rf
) && eq_generics(lg
, rg
) && both(lb
, rb
, |l
, r
| eq_block(l
, r
))
425 TyAlias(box ast
::TyAlias
{
432 TyAlias(box ast
::TyAlias
{
440 eq_defaultness(*ld
, *rd
)
441 && eq_generics(lg
, rg
)
442 && over(lb
, rb
, eq_generic_bound
)
443 && both(lt
, rt
, |l
, r
| eq_ty(l
, r
))
445 (MacCall(l
), MacCall(r
)) => eq_mac_call(l
, r
),
450 pub fn eq_assoc_item_kind(l
: &AssocItemKind
, r
: &AssocItemKind
) -> bool
{
451 use AssocItemKind
::*;
453 (Const(ld
, lt
, le
), Const(rd
, rt
, re
)) => eq_defaultness(*ld
, *rd
) && eq_ty(lt
, rt
) && eq_expr_opt(le
, re
),
468 eq_defaultness(*ld
, *rd
) && eq_fn_sig(lf
, rf
) && eq_generics(lg
, rg
) && both(lb
, rb
, |l
, r
| eq_block(l
, r
))
471 Type(box ast
::TyAlias
{
478 Type(box ast
::TyAlias
{
486 eq_defaultness(*ld
, *rd
)
487 && eq_generics(lg
, rg
)
488 && over(lb
, rb
, eq_generic_bound
)
489 && both(lt
, rt
, |l
, r
| eq_ty(l
, r
))
491 (MacCall(l
), MacCall(r
)) => eq_mac_call(l
, r
),
496 pub fn eq_variant(l
: &Variant
, r
: &Variant
) -> bool
{
497 l
.is_placeholder
== r
.is_placeholder
498 && over(&l
.attrs
, &r
.attrs
, eq_attr
)
499 && eq_vis(&l
.vis
, &r
.vis
)
500 && eq_id(l
.ident
, r
.ident
)
501 && eq_variant_data(&l
.data
, &r
.data
)
502 && both(&l
.disr_expr
, &r
.disr_expr
, |l
, r
| eq_expr(&l
.value
, &r
.value
))
505 pub fn eq_variant_data(l
: &VariantData
, r
: &VariantData
) -> bool
{
508 (Unit(_
), Unit(_
)) => true,
509 (Struct(l
, _
), Struct(r
, _
)) | (Tuple(l
, _
), Tuple(r
, _
)) => over(l
, r
, eq_struct_field
),
514 pub fn eq_struct_field(l
: &FieldDef
, r
: &FieldDef
) -> bool
{
515 l
.is_placeholder
== r
.is_placeholder
516 && over(&l
.attrs
, &r
.attrs
, eq_attr
)
517 && eq_vis(&l
.vis
, &r
.vis
)
518 && both(&l
.ident
, &r
.ident
, |l
, r
| eq_id(*l
, *r
))
519 && eq_ty(&l
.ty
, &r
.ty
)
522 pub fn eq_fn_sig(l
: &FnSig
, r
: &FnSig
) -> bool
{
523 eq_fn_decl(&l
.decl
, &r
.decl
) && eq_fn_header(&l
.header
, &r
.header
)
526 pub fn eq_fn_header(l
: &FnHeader
, r
: &FnHeader
) -> bool
{
527 matches
!(l
.unsafety
, Unsafe
::No
) == matches
!(r
.unsafety
, Unsafe
::No
)
528 && l
.asyncness
.is_async() == r
.asyncness
.is_async()
529 && matches
!(l
.constness
, Const
::No
) == matches
!(r
.constness
, Const
::No
)
530 && eq_ext(&l
.ext
, &r
.ext
)
533 pub fn eq_generics(l
: &Generics
, r
: &Generics
) -> bool
{
534 over(&l
.params
, &r
.params
, eq_generic_param
)
535 && over(&l
.where_clause
.predicates
, &r
.where_clause
.predicates
, |l
, r
| {
536 eq_where_predicate(l
, r
)
540 pub fn eq_where_predicate(l
: &WherePredicate
, r
: &WherePredicate
) -> bool
{
541 use WherePredicate
::*;
543 (BoundPredicate(l
), BoundPredicate(r
)) => {
544 over(&l
.bound_generic_params
, &r
.bound_generic_params
, |l
, r
| {
545 eq_generic_param(l
, r
)
546 }) && eq_ty(&l
.bounded_ty
, &r
.bounded_ty
)
547 && over(&l
.bounds
, &r
.bounds
, eq_generic_bound
)
549 (RegionPredicate(l
), RegionPredicate(r
)) => {
550 eq_id(l
.lifetime
.ident
, r
.lifetime
.ident
) && over(&l
.bounds
, &r
.bounds
, eq_generic_bound
)
552 (EqPredicate(l
), EqPredicate(r
)) => eq_ty(&l
.lhs_ty
, &r
.lhs_ty
) && eq_ty(&l
.rhs_ty
, &r
.rhs_ty
),
557 pub fn eq_use_tree(l
: &UseTree
, r
: &UseTree
) -> bool
{
558 eq_path(&l
.prefix
, &r
.prefix
) && eq_use_tree_kind(&l
.kind
, &r
.kind
)
561 pub fn eq_anon_const(l
: &AnonConst
, r
: &AnonConst
) -> bool
{
562 eq_expr(&l
.value
, &r
.value
)
565 pub fn eq_use_tree_kind(l
: &UseTreeKind
, r
: &UseTreeKind
) -> bool
{
568 (Glob
, Glob
) => true,
569 (Simple(l
), Simple(r
)) => both(l
, r
, |l
, r
| eq_id(*l
, *r
)),
570 (Nested(l
), Nested(r
)) => over(l
, r
, |(l
, _
), (r
, _
)| eq_use_tree(l
, r
)),
575 pub fn eq_defaultness(l
: Defaultness
, r
: Defaultness
) -> bool
{
578 (Defaultness
::Final
, Defaultness
::Final
) | (Defaultness
::Default(_
), Defaultness
::Default(_
))
582 pub fn eq_vis(l
: &Visibility
, r
: &Visibility
) -> bool
{
583 use VisibilityKind
::*;
584 match (&l
.kind
, &r
.kind
) {
585 (Public
, Public
) | (Inherited
, Inherited
) => true,
586 (Restricted { path: l, .. }
, Restricted { path: r, .. }
) => eq_path(l
, r
),
591 pub fn eq_fn_decl(l
: &FnDecl
, r
: &FnDecl
) -> bool
{
592 eq_fn_ret_ty(&l
.output
, &r
.output
)
593 && over(&l
.inputs
, &r
.inputs
, |l
, r
| {
594 l
.is_placeholder
== r
.is_placeholder
595 && eq_pat(&l
.pat
, &r
.pat
)
596 && eq_ty(&l
.ty
, &r
.ty
)
597 && over(&l
.attrs
, &r
.attrs
, eq_attr
)
601 pub fn eq_closure_binder(l
: &ClosureBinder
, r
: &ClosureBinder
) -> bool
{
603 (ClosureBinder
::NotPresent
, ClosureBinder
::NotPresent
) => true,
604 (ClosureBinder
::For { generic_params: lp, .. }
, ClosureBinder
::For { generic_params: rp, .. }
) => {
605 lp
.len() == rp
.len() && std
::iter
::zip(lp
.iter(), rp
.iter()).all(|(l
, r
)| eq_generic_param(l
, r
))
611 pub fn eq_fn_ret_ty(l
: &FnRetTy
, r
: &FnRetTy
) -> bool
{
613 (FnRetTy
::Default(_
), FnRetTy
::Default(_
)) => true,
614 (FnRetTy
::Ty(l
), FnRetTy
::Ty(r
)) => eq_ty(l
, r
),
619 pub fn eq_ty(l
: &Ty
, r
: &Ty
) -> bool
{
621 match (&l
.kind
, &r
.kind
) {
622 (Paren(l
), _
) => eq_ty(l
, r
),
623 (_
, Paren(r
)) => eq_ty(l
, r
),
624 (Never
, Never
) | (Infer
, Infer
) | (ImplicitSelf
, ImplicitSelf
) | (Err
, Err
) | (CVarArgs
, CVarArgs
) => true,
625 (Slice(l
), Slice(r
)) => eq_ty(l
, r
),
626 (Array(le
, ls
), Array(re
, rs
)) => eq_ty(le
, re
) && eq_expr(&ls
.value
, &rs
.value
),
627 (Ptr(l
), Ptr(r
)) => l
.mutbl
== r
.mutbl
&& eq_ty(&l
.ty
, &r
.ty
),
628 (Ref(ll
, l
), Ref(rl
, r
)) => {
629 both(ll
, rl
, |l
, r
| eq_id(l
.ident
, r
.ident
)) && l
.mutbl
== r
.mutbl
&& eq_ty(&l
.ty
, &r
.ty
)
631 (BareFn(l
), BareFn(r
)) => {
632 l
.unsafety
== r
.unsafety
633 && eq_ext(&l
.ext
, &r
.ext
)
634 && over(&l
.generic_params
, &r
.generic_params
, eq_generic_param
)
635 && eq_fn_decl(&l
.decl
, &r
.decl
)
637 (Tup(l
), Tup(r
)) => over(l
, r
, |l
, r
| eq_ty(l
, r
)),
638 (Path(lq
, lp
), Path(rq
, rp
)) => both(lq
, rq
, eq_qself
) && eq_path(lp
, rp
),
639 (TraitObject(lg
, ls
), TraitObject(rg
, rs
)) => ls
== rs
&& over(lg
, rg
, eq_generic_bound
),
640 (ImplTrait(_
, lg
), ImplTrait(_
, rg
)) => over(lg
, rg
, eq_generic_bound
),
641 (Typeof(l
), Typeof(r
)) => eq_expr(&l
.value
, &r
.value
),
642 (MacCall(l
), MacCall(r
)) => eq_mac_call(l
, r
),
647 pub fn eq_ext(l
: &Extern
, r
: &Extern
) -> bool
{
650 (None
, None
) | (Implicit(_
), Implicit(_
)) => true,
651 (Explicit(l
, _
), Explicit(r
, _
)) => eq_str_lit(l
, r
),
656 pub fn eq_str_lit(l
: &StrLit
, r
: &StrLit
) -> bool
{
657 l
.style
== r
.style
&& l
.symbol
== r
.symbol
&& l
.suffix
== r
.suffix
660 pub fn eq_poly_ref_trait(l
: &PolyTraitRef
, r
: &PolyTraitRef
) -> bool
{
661 eq_path(&l
.trait_ref
.path
, &r
.trait_ref
.path
)
662 && over(&l
.bound_generic_params
, &r
.bound_generic_params
, |l
, r
| {
663 eq_generic_param(l
, r
)
667 pub fn eq_generic_param(l
: &GenericParam
, r
: &GenericParam
) -> bool
{
668 use GenericParamKind
::*;
669 l
.is_placeholder
== r
.is_placeholder
670 && eq_id(l
.ident
, r
.ident
)
671 && over(&l
.bounds
, &r
.bounds
, eq_generic_bound
)
672 && match (&l
.kind
, &r
.kind
) {
673 (Lifetime
, Lifetime
) => true,
674 (Type { default: l }
, Type { default: r }
) => both(l
, r
, |l
, r
| eq_ty(l
, r
)),
686 ) => eq_ty(lt
, rt
) && both(ld
, rd
, eq_anon_const
),
689 && over(&l
.attrs
, &r
.attrs
, eq_attr
)
692 pub fn eq_generic_bound(l
: &GenericBound
, r
: &GenericBound
) -> bool
{
695 (Trait(ptr1
, tbm1
), Trait(ptr2
, tbm2
)) => tbm1
== tbm2
&& eq_poly_ref_trait(ptr1
, ptr2
),
696 (Outlives(l
), Outlives(r
)) => eq_id(l
.ident
, r
.ident
),
701 fn eq_term(l
: &Term
, r
: &Term
) -> bool
{
703 (Term
::Ty(l
), Term
::Ty(r
)) => eq_ty(l
, r
),
704 (Term
::Const(l
), Term
::Const(r
)) => eq_anon_const(l
, r
),
709 pub fn eq_assoc_constraint(l
: &AssocConstraint
, r
: &AssocConstraint
) -> bool
{
710 use AssocConstraintKind
::*;
711 eq_id(l
.ident
, r
.ident
)
712 && match (&l
.kind
, &r
.kind
) {
713 (Equality { term: l }
, Equality { term: r }
) => eq_term(l
, r
),
714 (Bound { bounds: l }
, Bound { bounds: r }
) => over(l
, r
, eq_generic_bound
),
719 pub fn eq_mac_call(l
: &MacCall
, r
: &MacCall
) -> bool
{
720 eq_path(&l
.path
, &r
.path
) && eq_delim_args(&l
.args
, &r
.args
)
723 pub fn eq_attr(l
: &Attribute
, r
: &Attribute
) -> bool
{
726 && match (&l
.kind
, &r
.kind
) {
727 (DocComment(l1
, l2
), DocComment(r1
, r2
)) => l1
== r1
&& l2
== r2
,
728 (Normal(l
), Normal(r
)) => eq_path(&l
.item
.path
, &r
.item
.path
) && eq_attr_args(&l
.item
.args
, &r
.item
.args
),
733 pub fn eq_attr_args(l
: &AttrArgs
, r
: &AttrArgs
) -> bool
{
736 (Empty
, Empty
) => true,
737 (Delimited(la
), Delimited(ra
)) => eq_delim_args(la
, ra
),
738 (Eq(_
, AttrArgsEq
::Ast(le
)), Eq(_
, AttrArgsEq
::Ast(re
))) => eq_expr(le
, re
),
739 (Eq(_
, AttrArgsEq
::Hir(ll
)), Eq(_
, AttrArgsEq
::Hir(rl
))) => ll
.kind
== rl
.kind
,
744 pub fn eq_delim_args(l
: &DelimArgs
, r
: &DelimArgs
) -> bool
{
745 l
.delim
== r
.delim
&& l
.tokens
.eq_unspanned(&r
.tokens
)