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 (Try(l
), Try(r
)) | (Await(l
, _
), Await(r
, _
)) => eq_expr(l
, r
),
147 (Array(l
), Array(r
)) => over(l
, r
, |l
, r
| eq_expr(l
, r
)),
148 (Tup(l
), Tup(r
)) => over(l
, r
, |l
, r
| eq_expr(l
, r
)),
149 (Repeat(le
, ls
), Repeat(re
, rs
)) => eq_expr(le
, re
) && eq_expr(&ls
.value
, &rs
.value
),
150 (Call(lc
, la
), Call(rc
, ra
)) => eq_expr(lc
, rc
) && over(la
, ra
, |l
, r
| eq_expr(l
, r
)),
152 MethodCall(box ast
::MethodCall
{
158 MethodCall(box ast
::MethodCall
{
164 ) => eq_path_seg(ls
, rs
) && eq_expr(lr
, rr
) && over(la
, ra
, |l
, r
| eq_expr(l
, r
)),
165 (Binary(lo
, ll
, lr
), Binary(ro
, rl
, rr
)) => lo
.node
== ro
.node
&& eq_expr(ll
, rl
) && eq_expr(lr
, rr
),
166 (Unary(lo
, l
), Unary(ro
, r
)) => mem
::discriminant(lo
) == mem
::discriminant(ro
) && eq_expr(l
, r
),
167 (Lit(l
), Lit(r
)) => l
== r
,
168 (Cast(l
, lt
), Cast(r
, rt
)) | (Type(l
, lt
), Type(r
, rt
)) => eq_expr(l
, r
) && eq_ty(lt
, rt
),
169 (Let(lp
, le
, _
, _
), Let(rp
, re
, _
, _
)) => eq_pat(lp
, rp
) && eq_expr(le
, re
),
170 (If(lc
, lt
, le
), If(rc
, rt
, re
)) => eq_expr(lc
, rc
) && eq_block(lt
, rt
) && eq_expr_opt(le
, re
),
171 (While(lc
, lt
, ll
), While(rc
, rt
, rl
)) => eq_label(ll
, rl
) && eq_expr(lc
, rc
) && eq_block(lt
, rt
),
172 (ForLoop(lp
, li
, lt
, ll
), ForLoop(rp
, ri
, rt
, rl
)) => {
173 eq_label(ll
, rl
) && eq_pat(lp
, rp
) && eq_expr(li
, ri
) && eq_block(lt
, rt
)
175 (Loop(lt
, ll
, _
), Loop(rt
, rl
, _
)) => eq_label(ll
, rl
) && eq_block(lt
, rt
),
176 (Block(lb
, ll
), Block(rb
, rl
)) => eq_label(ll
, rl
) && eq_block(lb
, rb
),
177 (TryBlock(l
), TryBlock(r
)) => eq_block(l
, r
),
178 (Yield(l
), Yield(r
)) | (Ret(l
), Ret(r
)) => eq_expr_opt(l
, r
),
179 (Break(ll
, le
), Break(rl
, re
)) => eq_label(ll
, rl
) && eq_expr_opt(le
, re
),
180 (Continue(ll
), Continue(rl
)) => eq_label(ll
, rl
),
181 (Assign(l1
, l2
, _
), Assign(r1
, r2
, _
)) | (Index(l1
, l2
, _
), Index(r1
, r2
, _
)) => {
182 eq_expr(l1
, r1
) && eq_expr(l2
, r2
)
184 (AssignOp(lo
, lp
, lv
), AssignOp(ro
, rp
, rv
)) => lo
.node
== ro
.node
&& eq_expr(lp
, rp
) && eq_expr(lv
, rv
),
185 (Field(lp
, lf
), Field(rp
, rf
)) => eq_id(*lf
, *rf
) && eq_expr(lp
, rp
),
186 (Match(ls
, la
), Match(rs
, ra
)) => eq_expr(ls
, rs
) && over(la
, ra
, eq_arm
),
188 Closure(box ast
::Closure
{
197 Closure(box ast
::Closure
{
207 eq_closure_binder(lb
, rb
)
209 && la
.is_async() == ra
.is_async()
211 && eq_fn_decl(lf
, rf
)
214 (Async(lc
, lb
), Async(rc
, rb
)) => lc
== rc
&& eq_block(lb
, rb
),
215 (Range(lf
, lt
, ll
), Range(rf
, rt
, rl
)) => ll
== rl
&& eq_expr_opt(lf
, rf
) && eq_expr_opt(lt
, rt
),
216 (AddrOf(lbk
, lm
, le
), AddrOf(rbk
, rm
, re
)) => lbk
== rbk
&& lm
== rm
&& eq_expr(le
, re
),
217 (Path(lq
, lp
), Path(rq
, rp
)) => both(lq
, rq
, eq_qself
) && eq_path(lp
, rp
),
218 (MacCall(l
), MacCall(r
)) => eq_mac_call(l
, r
),
219 (Struct(lse
), Struct(rse
)) => {
220 eq_maybe_qself(&lse
.qself
, &rse
.qself
)
221 && eq_path(&lse
.path
, &rse
.path
)
222 && eq_struct_rest(&lse
.rest
, &rse
.rest
)
223 && unordered_over(&lse
.fields
, &rse
.fields
, eq_field
)
229 pub fn eq_field(l
: &ExprField
, r
: &ExprField
) -> bool
{
230 l
.is_placeholder
== r
.is_placeholder
231 && eq_id(l
.ident
, r
.ident
)
232 && eq_expr(&l
.expr
, &r
.expr
)
233 && over(&l
.attrs
, &r
.attrs
, eq_attr
)
236 pub fn eq_arm(l
: &Arm
, r
: &Arm
) -> bool
{
237 l
.is_placeholder
== r
.is_placeholder
238 && eq_pat(&l
.pat
, &r
.pat
)
239 && eq_expr(&l
.body
, &r
.body
)
240 && eq_expr_opt(&l
.guard
, &r
.guard
)
241 && over(&l
.attrs
, &r
.attrs
, eq_attr
)
244 pub fn eq_label(l
: &Option
<Label
>, r
: &Option
<Label
>) -> bool
{
245 both(l
, r
, |l
, r
| eq_id(l
.ident
, r
.ident
))
248 pub fn eq_block(l
: &Block
, r
: &Block
) -> bool
{
249 l
.rules
== r
.rules
&& over(&l
.stmts
, &r
.stmts
, eq_stmt
)
252 pub fn eq_stmt(l
: &Stmt
, r
: &Stmt
) -> bool
{
254 match (&l
.kind
, &r
.kind
) {
255 (Local(l
), Local(r
)) => {
256 eq_pat(&l
.pat
, &r
.pat
)
257 && both(&l
.ty
, &r
.ty
, |l
, r
| eq_ty(l
, r
))
258 && eq_local_kind(&l
.kind
, &r
.kind
)
259 && over(&l
.attrs
, &r
.attrs
, eq_attr
)
261 (Item(l
), Item(r
)) => eq_item(l
, r
, eq_item_kind
),
262 (Expr(l
), Expr(r
)) | (Semi(l
), Semi(r
)) => eq_expr(l
, r
),
263 (Empty
, Empty
) => true,
264 (MacCall(l
), MacCall(r
)) => {
265 l
.style
== r
.style
&& eq_mac_call(&l
.mac
, &r
.mac
) && over(&l
.attrs
, &r
.attrs
, eq_attr
)
271 pub fn eq_local_kind(l
: &LocalKind
, r
: &LocalKind
) -> bool
{
274 (Decl
, Decl
) => true,
275 (Init(l
), Init(r
)) => eq_expr(l
, r
),
276 (InitElse(li
, le
), InitElse(ri
, re
)) => eq_expr(li
, ri
) && eq_block(le
, re
),
281 pub fn eq_item
<K
>(l
: &Item
<K
>, r
: &Item
<K
>, mut eq_kind
: impl FnMut(&K
, &K
) -> bool
) -> bool
{
282 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
)
285 #[expect(clippy::too_many_lines)] // Just a big match statement
286 pub fn eq_item_kind(l
: &ItemKind
, r
: &ItemKind
) -> bool
{
289 (ExternCrate(l
), ExternCrate(r
)) => l
== r
,
290 (Use(l
), Use(r
)) => eq_use_tree(l
, r
),
292 Static(box ast
::StaticItem
{
297 Static(box ast
::StaticItem
{
302 ) => lm
== rm
&& eq_ty(lt
, rt
) && eq_expr_opt(le
, re
),
304 Const(box ast
::ConstItem
{
310 Const(box ast
::ConstItem
{
316 ) => eq_defaultness(*ld
, *rd
) && eq_generics(lg
, rg
) && eq_ty(lt
, rt
) && eq_expr_opt(le
, re
),
331 eq_defaultness(*ld
, *rd
) && eq_fn_sig(lf
, rf
) && eq_generics(lg
, rg
) && both(lb
, rb
, |l
, r
| eq_block(l
, r
))
333 (Mod(lu
, lmk
), Mod(ru
, rmk
)) => {
335 && match (lmk
, rmk
) {
336 (ModKind
::Loaded(litems
, linline
, _
), ModKind
::Loaded(ritems
, rinline
, _
)) => {
337 linline
== rinline
&& over(litems
, ritems
, |l
, r
| eq_item(l
, r
, eq_item_kind
))
339 (ModKind
::Unloaded
, ModKind
::Unloaded
) => true,
343 (ForeignMod(l
), ForeignMod(r
)) => {
344 both(&l
.abi
, &r
.abi
, eq_str_lit
) && over(&l
.items
, &r
.items
, |l
, r
| eq_item(l
, r
, eq_foreign_item_kind
))
347 TyAlias(box ast
::TyAlias
{
354 TyAlias(box ast
::TyAlias
{
362 eq_defaultness(*ld
, *rd
)
363 && eq_generics(lg
, rg
)
364 && over(lb
, rb
, eq_generic_bound
)
365 && both(lt
, rt
, |l
, r
| eq_ty(l
, r
))
367 (Enum(le
, lg
), Enum(re
, rg
)) => over(&le
.variants
, &re
.variants
, eq_variant
) && eq_generics(lg
, rg
),
368 (Struct(lv
, lg
), Struct(rv
, rg
)) | (Union(lv
, lg
), Union(rv
, rg
)) => {
369 eq_variant_data(lv
, rv
) && eq_generics(lg
, rg
)
372 Trait(box ast
::Trait
{
379 Trait(box ast
::Trait
{
388 && matches
!(lu
, Unsafe
::No
) == matches
!(ru
, Unsafe
::No
)
389 && eq_generics(lg
, rg
)
390 && over(lb
, rb
, eq_generic_bound
)
391 && over(li
, ri
, |l
, r
| eq_item(l
, r
, eq_assoc_item_kind
))
393 (TraitAlias(lg
, lb
), TraitAlias(rg
, rb
)) => eq_generics(lg
, rg
) && over(lb
, rb
, eq_generic_bound
),
416 matches
!(lu
, Unsafe
::No
) == matches
!(ru
, Unsafe
::No
)
417 && matches
!(lp
, ImplPolarity
::Positive
) == matches
!(rp
, ImplPolarity
::Positive
)
418 && eq_defaultness(*ld
, *rd
)
419 && matches
!(lc
, ast
::Const
::No
) == matches
!(rc
, ast
::Const
::No
)
420 && eq_generics(lg
, rg
)
421 && both(lot
, rot
, |l
, r
| eq_path(&l
.path
, &r
.path
))
423 && over(li
, ri
, |l
, r
| eq_item(l
, r
, eq_assoc_item_kind
))
425 (MacCall(l
), MacCall(r
)) => eq_mac_call(l
, r
),
426 (MacroDef(l
), MacroDef(r
)) => l
.macro_rules
== r
.macro_rules
&& eq_delim_args(&l
.body
, &r
.body
),
431 pub fn eq_foreign_item_kind(l
: &ForeignItemKind
, r
: &ForeignItemKind
) -> bool
{
432 use ForeignItemKind
::*;
434 (Static(lt
, lm
, le
), Static(rt
, rm
, re
)) => lm
== rm
&& eq_ty(lt
, rt
) && eq_expr_opt(le
, re
),
449 eq_defaultness(*ld
, *rd
) && eq_fn_sig(lf
, rf
) && eq_generics(lg
, rg
) && both(lb
, rb
, |l
, r
| eq_block(l
, r
))
452 TyAlias(box ast
::TyAlias
{
459 TyAlias(box ast
::TyAlias
{
467 eq_defaultness(*ld
, *rd
)
468 && eq_generics(lg
, rg
)
469 && over(lb
, rb
, eq_generic_bound
)
470 && both(lt
, rt
, |l
, r
| eq_ty(l
, r
))
472 (MacCall(l
), MacCall(r
)) => eq_mac_call(l
, r
),
477 pub fn eq_assoc_item_kind(l
: &AssocItemKind
, r
: &AssocItemKind
) -> bool
{
478 use AssocItemKind
::*;
481 Const(box ast
::ConstItem
{
487 Const(box ast
::ConstItem
{
493 ) => eq_defaultness(*ld
, *rd
) && eq_generics(lg
, rg
) && eq_ty(lt
, rt
) && eq_expr_opt(le
, re
),
508 eq_defaultness(*ld
, *rd
) && eq_fn_sig(lf
, rf
) && eq_generics(lg
, rg
) && both(lb
, rb
, |l
, r
| eq_block(l
, r
))
511 Type(box ast
::TyAlias
{
518 Type(box ast
::TyAlias
{
526 eq_defaultness(*ld
, *rd
)
527 && eq_generics(lg
, rg
)
528 && over(lb
, rb
, eq_generic_bound
)
529 && both(lt
, rt
, |l
, r
| eq_ty(l
, r
))
531 (MacCall(l
), MacCall(r
)) => eq_mac_call(l
, r
),
536 pub fn eq_variant(l
: &Variant
, r
: &Variant
) -> bool
{
537 l
.is_placeholder
== r
.is_placeholder
538 && over(&l
.attrs
, &r
.attrs
, eq_attr
)
539 && eq_vis(&l
.vis
, &r
.vis
)
540 && eq_id(l
.ident
, r
.ident
)
541 && eq_variant_data(&l
.data
, &r
.data
)
542 && both(&l
.disr_expr
, &r
.disr_expr
, |l
, r
| eq_expr(&l
.value
, &r
.value
))
545 pub fn eq_variant_data(l
: &VariantData
, r
: &VariantData
) -> bool
{
548 (Unit(_
), Unit(_
)) => true,
549 (Struct(l
, _
), Struct(r
, _
)) | (Tuple(l
, _
), Tuple(r
, _
)) => over(l
, r
, eq_struct_field
),
554 pub fn eq_struct_field(l
: &FieldDef
, r
: &FieldDef
) -> bool
{
555 l
.is_placeholder
== r
.is_placeholder
556 && over(&l
.attrs
, &r
.attrs
, eq_attr
)
557 && eq_vis(&l
.vis
, &r
.vis
)
558 && both(&l
.ident
, &r
.ident
, |l
, r
| eq_id(*l
, *r
))
559 && eq_ty(&l
.ty
, &r
.ty
)
562 pub fn eq_fn_sig(l
: &FnSig
, r
: &FnSig
) -> bool
{
563 eq_fn_decl(&l
.decl
, &r
.decl
) && eq_fn_header(&l
.header
, &r
.header
)
566 pub fn eq_fn_header(l
: &FnHeader
, r
: &FnHeader
) -> bool
{
567 matches
!(l
.unsafety
, Unsafe
::No
) == matches
!(r
.unsafety
, Unsafe
::No
)
568 && l
.asyncness
.is_async() == r
.asyncness
.is_async()
569 && matches
!(l
.constness
, Const
::No
) == matches
!(r
.constness
, Const
::No
)
570 && eq_ext(&l
.ext
, &r
.ext
)
573 pub fn eq_generics(l
: &Generics
, r
: &Generics
) -> bool
{
574 over(&l
.params
, &r
.params
, eq_generic_param
)
575 && over(&l
.where_clause
.predicates
, &r
.where_clause
.predicates
, |l
, r
| {
576 eq_where_predicate(l
, r
)
580 pub fn eq_where_predicate(l
: &WherePredicate
, r
: &WherePredicate
) -> bool
{
581 use WherePredicate
::*;
583 (BoundPredicate(l
), BoundPredicate(r
)) => {
584 over(&l
.bound_generic_params
, &r
.bound_generic_params
, |l
, r
| {
585 eq_generic_param(l
, r
)
586 }) && eq_ty(&l
.bounded_ty
, &r
.bounded_ty
)
587 && over(&l
.bounds
, &r
.bounds
, eq_generic_bound
)
589 (RegionPredicate(l
), RegionPredicate(r
)) => {
590 eq_id(l
.lifetime
.ident
, r
.lifetime
.ident
) && over(&l
.bounds
, &r
.bounds
, eq_generic_bound
)
592 (EqPredicate(l
), EqPredicate(r
)) => eq_ty(&l
.lhs_ty
, &r
.lhs_ty
) && eq_ty(&l
.rhs_ty
, &r
.rhs_ty
),
597 pub fn eq_use_tree(l
: &UseTree
, r
: &UseTree
) -> bool
{
598 eq_path(&l
.prefix
, &r
.prefix
) && eq_use_tree_kind(&l
.kind
, &r
.kind
)
601 pub fn eq_anon_const(l
: &AnonConst
, r
: &AnonConst
) -> bool
{
602 eq_expr(&l
.value
, &r
.value
)
605 pub fn eq_use_tree_kind(l
: &UseTreeKind
, r
: &UseTreeKind
) -> bool
{
608 (Glob
, Glob
) => true,
609 (Simple(l
), Simple(r
)) => both(l
, r
, |l
, r
| eq_id(*l
, *r
)),
610 (Nested(l
), Nested(r
)) => over(l
, r
, |(l
, _
), (r
, _
)| eq_use_tree(l
, r
)),
615 pub fn eq_defaultness(l
: Defaultness
, r
: Defaultness
) -> bool
{
618 (Defaultness
::Final
, Defaultness
::Final
) | (Defaultness
::Default(_
), Defaultness
::Default(_
))
622 pub fn eq_vis(l
: &Visibility
, r
: &Visibility
) -> bool
{
623 use VisibilityKind
::*;
624 match (&l
.kind
, &r
.kind
) {
625 (Public
, Public
) | (Inherited
, Inherited
) => true,
626 (Restricted { path: l, .. }
, Restricted { path: r, .. }
) => eq_path(l
, r
),
631 pub fn eq_fn_decl(l
: &FnDecl
, r
: &FnDecl
) -> bool
{
632 eq_fn_ret_ty(&l
.output
, &r
.output
)
633 && over(&l
.inputs
, &r
.inputs
, |l
, r
| {
634 l
.is_placeholder
== r
.is_placeholder
635 && eq_pat(&l
.pat
, &r
.pat
)
636 && eq_ty(&l
.ty
, &r
.ty
)
637 && over(&l
.attrs
, &r
.attrs
, eq_attr
)
641 pub fn eq_closure_binder(l
: &ClosureBinder
, r
: &ClosureBinder
) -> bool
{
643 (ClosureBinder
::NotPresent
, ClosureBinder
::NotPresent
) => true,
644 (ClosureBinder
::For { generic_params: lp, .. }
, ClosureBinder
::For { generic_params: rp, .. }
) => {
645 lp
.len() == rp
.len() && std
::iter
::zip(lp
.iter(), rp
.iter()).all(|(l
, r
)| eq_generic_param(l
, r
))
651 pub fn eq_fn_ret_ty(l
: &FnRetTy
, r
: &FnRetTy
) -> bool
{
653 (FnRetTy
::Default(_
), FnRetTy
::Default(_
)) => true,
654 (FnRetTy
::Ty(l
), FnRetTy
::Ty(r
)) => eq_ty(l
, r
),
659 pub fn eq_ty(l
: &Ty
, r
: &Ty
) -> bool
{
661 match (&l
.kind
, &r
.kind
) {
662 (Paren(l
), _
) => eq_ty(l
, r
),
663 (_
, Paren(r
)) => eq_ty(l
, r
),
664 (Never
, Never
) | (Infer
, Infer
) | (ImplicitSelf
, ImplicitSelf
) | (Err
, Err
) | (CVarArgs
, CVarArgs
) => true,
665 (Slice(l
), Slice(r
)) => eq_ty(l
, r
),
666 (Array(le
, ls
), Array(re
, rs
)) => eq_ty(le
, re
) && eq_expr(&ls
.value
, &rs
.value
),
667 (Ptr(l
), Ptr(r
)) => l
.mutbl
== r
.mutbl
&& eq_ty(&l
.ty
, &r
.ty
),
668 (Ref(ll
, l
), Ref(rl
, r
)) => {
669 both(ll
, rl
, |l
, r
| eq_id(l
.ident
, r
.ident
)) && l
.mutbl
== r
.mutbl
&& eq_ty(&l
.ty
, &r
.ty
)
671 (BareFn(l
), BareFn(r
)) => {
672 l
.unsafety
== r
.unsafety
673 && eq_ext(&l
.ext
, &r
.ext
)
674 && over(&l
.generic_params
, &r
.generic_params
, eq_generic_param
)
675 && eq_fn_decl(&l
.decl
, &r
.decl
)
677 (Tup(l
), Tup(r
)) => over(l
, r
, |l
, r
| eq_ty(l
, r
)),
678 (Path(lq
, lp
), Path(rq
, rp
)) => both(lq
, rq
, eq_qself
) && eq_path(lp
, rp
),
679 (TraitObject(lg
, ls
), TraitObject(rg
, rs
)) => ls
== rs
&& over(lg
, rg
, eq_generic_bound
),
680 (ImplTrait(_
, lg
), ImplTrait(_
, rg
)) => over(lg
, rg
, eq_generic_bound
),
681 (Typeof(l
), Typeof(r
)) => eq_expr(&l
.value
, &r
.value
),
682 (MacCall(l
), MacCall(r
)) => eq_mac_call(l
, r
),
687 pub fn eq_ext(l
: &Extern
, r
: &Extern
) -> bool
{
690 (None
, None
) | (Implicit(_
), Implicit(_
)) => true,
691 (Explicit(l
, _
), Explicit(r
, _
)) => eq_str_lit(l
, r
),
696 pub fn eq_str_lit(l
: &StrLit
, r
: &StrLit
) -> bool
{
697 l
.style
== r
.style
&& l
.symbol
== r
.symbol
&& l
.suffix
== r
.suffix
700 pub fn eq_poly_ref_trait(l
: &PolyTraitRef
, r
: &PolyTraitRef
) -> bool
{
701 eq_path(&l
.trait_ref
.path
, &r
.trait_ref
.path
)
702 && over(&l
.bound_generic_params
, &r
.bound_generic_params
, |l
, r
| {
703 eq_generic_param(l
, r
)
707 pub fn eq_generic_param(l
: &GenericParam
, r
: &GenericParam
) -> bool
{
708 use GenericParamKind
::*;
709 l
.is_placeholder
== r
.is_placeholder
710 && eq_id(l
.ident
, r
.ident
)
711 && over(&l
.bounds
, &r
.bounds
, eq_generic_bound
)
712 && match (&l
.kind
, &r
.kind
) {
713 (Lifetime
, Lifetime
) => true,
714 (Type { default: l }
, Type { default: r }
) => both(l
, r
, |l
, r
| eq_ty(l
, r
)),
726 ) => eq_ty(lt
, rt
) && both(ld
, rd
, eq_anon_const
),
729 && over(&l
.attrs
, &r
.attrs
, eq_attr
)
732 pub fn eq_generic_bound(l
: &GenericBound
, r
: &GenericBound
) -> bool
{
735 (Trait(ptr1
, tbm1
), Trait(ptr2
, tbm2
)) => tbm1
== tbm2
&& eq_poly_ref_trait(ptr1
, ptr2
),
736 (Outlives(l
), Outlives(r
)) => eq_id(l
.ident
, r
.ident
),
741 fn eq_term(l
: &Term
, r
: &Term
) -> bool
{
743 (Term
::Ty(l
), Term
::Ty(r
)) => eq_ty(l
, r
),
744 (Term
::Const(l
), Term
::Const(r
)) => eq_anon_const(l
, r
),
749 pub fn eq_assoc_constraint(l
: &AssocConstraint
, r
: &AssocConstraint
) -> bool
{
750 use AssocConstraintKind
::*;
751 eq_id(l
.ident
, r
.ident
)
752 && match (&l
.kind
, &r
.kind
) {
753 (Equality { term: l }
, Equality { term: r }
) => eq_term(l
, r
),
754 (Bound { bounds: l }
, Bound { bounds: r }
) => over(l
, r
, eq_generic_bound
),
759 pub fn eq_mac_call(l
: &MacCall
, r
: &MacCall
) -> bool
{
760 eq_path(&l
.path
, &r
.path
) && eq_delim_args(&l
.args
, &r
.args
)
763 pub fn eq_attr(l
: &Attribute
, r
: &Attribute
) -> bool
{
766 && match (&l
.kind
, &r
.kind
) {
767 (DocComment(l1
, l2
), DocComment(r1
, r2
)) => l1
== r1
&& l2
== r2
,
768 (Normal(l
), Normal(r
)) => eq_path(&l
.item
.path
, &r
.item
.path
) && eq_attr_args(&l
.item
.args
, &r
.item
.args
),
773 pub fn eq_attr_args(l
: &AttrArgs
, r
: &AttrArgs
) -> bool
{
776 (Empty
, Empty
) => true,
777 (Delimited(la
), Delimited(ra
)) => eq_delim_args(la
, ra
),
778 (Eq(_
, AttrArgsEq
::Ast(le
)), Eq(_
, AttrArgsEq
::Ast(re
))) => eq_expr(le
, re
),
779 (Eq(_
, AttrArgsEq
::Hir(ll
)), Eq(_
, AttrArgsEq
::Hir(rl
))) => ll
.kind
== rl
.kind
,
784 pub fn eq_delim_args(l
: &DelimArgs
, r
: &DelimArgs
) -> bool
{
785 l
.delim
== r
.delim
&& l
.tokens
.eq_unspanned(&r
.tokens
)