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
: &QSelf
, r
: &QSelf
) -> bool
{
79 l
.position
== r
.position
&& eq_ty(&l
.ty
, &r
.ty
)
82 pub fn eq_maybe_qself(l
: &Option
<QSelf
>, r
: &Option
<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
)),
150 (MethodCall(lc
, la
, _
), MethodCall(rc
, ra
, _
)) => eq_path_seg(lc
, rc
) && over(la
, ra
, |l
, r
| eq_expr(l
, r
)),
151 (Binary(lo
, ll
, lr
), Binary(ro
, rl
, rr
)) => lo
.node
== ro
.node
&& eq_expr(ll
, rl
) && eq_expr(lr
, rr
),
152 (Unary(lo
, l
), Unary(ro
, r
)) => mem
::discriminant(lo
) == mem
::discriminant(ro
) && eq_expr(l
, r
),
153 (Lit(l
), Lit(r
)) => l
.kind
== r
.kind
,
154 (Cast(l
, lt
), Cast(r
, rt
)) | (Type(l
, lt
), Type(r
, rt
)) => eq_expr(l
, r
) && eq_ty(lt
, rt
),
155 (Let(lp
, le
, _
), Let(rp
, re
, _
)) => eq_pat(lp
, rp
) && eq_expr(le
, re
),
156 (If(lc
, lt
, le
), If(rc
, rt
, re
)) => eq_expr(lc
, rc
) && eq_block(lt
, rt
) && eq_expr_opt(le
, re
),
157 (While(lc
, lt
, ll
), While(rc
, rt
, rl
)) => eq_label(ll
, rl
) && eq_expr(lc
, rc
) && eq_block(lt
, rt
),
158 (ForLoop(lp
, li
, lt
, ll
), ForLoop(rp
, ri
, rt
, rl
)) => {
159 eq_label(ll
, rl
) && eq_pat(lp
, rp
) && eq_expr(li
, ri
) && eq_block(lt
, rt
)
161 (Loop(lt
, ll
), Loop(rt
, rl
)) => eq_label(ll
, rl
) && eq_block(lt
, rt
),
162 (Block(lb
, ll
), Block(rb
, rl
)) => eq_label(ll
, rl
) && eq_block(lb
, rb
),
163 (TryBlock(l
), TryBlock(r
)) => eq_block(l
, r
),
164 (Yield(l
), Yield(r
)) | (Ret(l
), Ret(r
)) => eq_expr_opt(l
, r
),
165 (Break(ll
, le
), Break(rl
, re
)) => eq_label(ll
, rl
) && eq_expr_opt(le
, re
),
166 (Continue(ll
), Continue(rl
)) => eq_label(ll
, rl
),
167 (Assign(l1
, l2
, _
), Assign(r1
, r2
, _
)) | (Index(l1
, l2
), Index(r1
, r2
)) => eq_expr(l1
, r1
) && eq_expr(l2
, r2
),
168 (AssignOp(lo
, lp
, lv
), AssignOp(ro
, rp
, rv
)) => lo
.node
== ro
.node
&& eq_expr(lp
, rp
) && eq_expr(lv
, rv
),
169 (Field(lp
, lf
), Field(rp
, rf
)) => eq_id(*lf
, *rf
) && eq_expr(lp
, rp
),
170 (Match(ls
, la
), Match(rs
, ra
)) => eq_expr(ls
, rs
) && over(la
, ra
, eq_arm
),
171 (Closure(lc
, la
, lm
, lf
, lb
, _
), Closure(rc
, ra
, rm
, rf
, rb
, _
)) => {
172 lc
== rc
&& la
.is_async() == ra
.is_async() && lm
== rm
&& eq_fn_decl(lf
, rf
) && eq_expr(lb
, rb
)
174 (Async(lc
, _
, lb
), Async(rc
, _
, rb
)) => lc
== rc
&& eq_block(lb
, rb
),
175 (Range(lf
, lt
, ll
), Range(rf
, rt
, rl
)) => ll
== rl
&& eq_expr_opt(lf
, rf
) && eq_expr_opt(lt
, rt
),
176 (AddrOf(lbk
, lm
, le
), AddrOf(rbk
, rm
, re
)) => lbk
== rbk
&& lm
== rm
&& eq_expr(le
, re
),
177 (Path(lq
, lp
), Path(rq
, rp
)) => both(lq
, rq
, eq_qself
) && eq_path(lp
, rp
),
178 (MacCall(l
), MacCall(r
)) => eq_mac_call(l
, r
),
179 (Struct(lse
), Struct(rse
)) => {
180 eq_maybe_qself(&lse
.qself
, &rse
.qself
)
181 && eq_path(&lse
.path
, &rse
.path
)
182 && eq_struct_rest(&lse
.rest
, &rse
.rest
)
183 && unordered_over(&lse
.fields
, &rse
.fields
, eq_field
)
189 pub fn eq_field(l
: &ExprField
, r
: &ExprField
) -> bool
{
190 l
.is_placeholder
== r
.is_placeholder
191 && eq_id(l
.ident
, r
.ident
)
192 && eq_expr(&l
.expr
, &r
.expr
)
193 && over(&l
.attrs
, &r
.attrs
, eq_attr
)
196 pub fn eq_arm(l
: &Arm
, r
: &Arm
) -> bool
{
197 l
.is_placeholder
== r
.is_placeholder
198 && eq_pat(&l
.pat
, &r
.pat
)
199 && eq_expr(&l
.body
, &r
.body
)
200 && eq_expr_opt(&l
.guard
, &r
.guard
)
201 && over(&l
.attrs
, &r
.attrs
, eq_attr
)
204 pub fn eq_label(l
: &Option
<Label
>, r
: &Option
<Label
>) -> bool
{
205 both(l
, r
, |l
, r
| eq_id(l
.ident
, r
.ident
))
208 pub fn eq_block(l
: &Block
, r
: &Block
) -> bool
{
209 l
.rules
== r
.rules
&& over(&l
.stmts
, &r
.stmts
, eq_stmt
)
212 pub fn eq_stmt(l
: &Stmt
, r
: &Stmt
) -> bool
{
214 match (&l
.kind
, &r
.kind
) {
215 (Local(l
), Local(r
)) => {
216 eq_pat(&l
.pat
, &r
.pat
)
217 && both(&l
.ty
, &r
.ty
, |l
, r
| eq_ty(l
, r
))
218 && eq_local_kind(&l
.kind
, &r
.kind
)
219 && over(&l
.attrs
, &r
.attrs
, eq_attr
)
221 (Item(l
), Item(r
)) => eq_item(l
, r
, eq_item_kind
),
222 (Expr(l
), Expr(r
)) | (Semi(l
), Semi(r
)) => eq_expr(l
, r
),
223 (Empty
, Empty
) => true,
224 (MacCall(l
), MacCall(r
)) => {
225 l
.style
== r
.style
&& eq_mac_call(&l
.mac
, &r
.mac
) && over(&l
.attrs
, &r
.attrs
, eq_attr
)
231 pub fn eq_local_kind(l
: &LocalKind
, r
: &LocalKind
) -> bool
{
234 (Decl
, Decl
) => true,
235 (Init(l
), Init(r
)) => eq_expr(l
, r
),
236 (InitElse(li
, le
), InitElse(ri
, re
)) => eq_expr(li
, ri
) && eq_block(le
, re
),
241 pub fn eq_item
<K
>(l
: &Item
<K
>, r
: &Item
<K
>, mut eq_kind
: impl FnMut(&K
, &K
) -> bool
) -> bool
{
242 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
)
245 #[allow(clippy::too_many_lines)] // Just a big match statement
246 pub fn eq_item_kind(l
: &ItemKind
, r
: &ItemKind
) -> bool
{
249 (ExternCrate(l
), ExternCrate(r
)) => l
== r
,
250 (Use(l
), Use(r
)) => eq_use_tree(l
, r
),
251 (Static(lt
, lm
, le
), Static(rt
, rm
, re
)) => lm
== rm
&& eq_ty(lt
, rt
) && eq_expr_opt(le
, re
),
252 (Const(ld
, lt
, le
), Const(rd
, rt
, re
)) => eq_defaultness(*ld
, *rd
) && eq_ty(lt
, rt
) && eq_expr_opt(le
, re
),
267 eq_defaultness(*ld
, *rd
) && eq_fn_sig(lf
, rf
) && eq_generics(lg
, rg
) && both(lb
, rb
, |l
, r
| eq_block(l
, r
))
269 (Mod(lu
, lmk
), Mod(ru
, rmk
)) => {
271 && match (lmk
, rmk
) {
272 (ModKind
::Loaded(litems
, linline
, _
), ModKind
::Loaded(ritems
, rinline
, _
)) => {
273 linline
== rinline
&& over(litems
, ritems
, |l
, r
| eq_item(l
, r
, eq_item_kind
))
275 (ModKind
::Unloaded
, ModKind
::Unloaded
) => true,
279 (ForeignMod(l
), ForeignMod(r
)) => {
280 both(&l
.abi
, &r
.abi
, eq_str_lit
) && over(&l
.items
, &r
.items
, |l
, r
| eq_item(l
, r
, eq_foreign_item_kind
))
283 TyAlias(box ast
::TyAlias
{
289 TyAlias(box ast
::TyAlias
{
296 eq_defaultness(*ld
, *rd
)
297 && eq_generics(lg
, rg
)
298 && over(lb
, rb
, eq_generic_bound
)
299 && both(lt
, rt
, |l
, r
| eq_ty(l
, r
))
301 (Enum(le
, lg
), Enum(re
, rg
)) => over(&le
.variants
, &re
.variants
, eq_variant
) && eq_generics(lg
, rg
),
302 (Struct(lv
, lg
), Struct(rv
, rg
)) | (Union(lv
, lg
), Union(rv
, rg
)) => {
303 eq_variant_data(lv
, rv
) && eq_generics(lg
, rg
)
306 Trait(box ast
::Trait
{
313 Trait(box ast
::Trait
{
322 && matches
!(lu
, Unsafe
::No
) == matches
!(ru
, Unsafe
::No
)
323 && eq_generics(lg
, rg
)
324 && over(lb
, rb
, eq_generic_bound
)
325 && over(li
, ri
, |l
, r
| eq_item(l
, r
, eq_assoc_item_kind
))
327 (TraitAlias(lg
, lb
), TraitAlias(rg
, rb
)) => eq_generics(lg
, rg
) && over(lb
, rb
, eq_generic_bound
),
350 matches
!(lu
, Unsafe
::No
) == matches
!(ru
, Unsafe
::No
)
351 && matches
!(lp
, ImplPolarity
::Positive
) == matches
!(rp
, ImplPolarity
::Positive
)
352 && eq_defaultness(*ld
, *rd
)
353 && matches
!(lc
, ast
::Const
::No
) == matches
!(rc
, ast
::Const
::No
)
354 && eq_generics(lg
, rg
)
355 && both(lot
, rot
, |l
, r
| eq_path(&l
.path
, &r
.path
))
357 && over(li
, ri
, |l
, r
| eq_item(l
, r
, eq_assoc_item_kind
))
359 (MacCall(l
), MacCall(r
)) => eq_mac_call(l
, r
),
360 (MacroDef(l
), MacroDef(r
)) => l
.macro_rules
== r
.macro_rules
&& eq_mac_args(&l
.body
, &r
.body
),
365 pub fn eq_foreign_item_kind(l
: &ForeignItemKind
, r
: &ForeignItemKind
) -> bool
{
366 use ForeignItemKind
::*;
368 (Static(lt
, lm
, le
), Static(rt
, rm
, re
)) => lm
== rm
&& eq_ty(lt
, rt
) && eq_expr_opt(le
, re
),
383 eq_defaultness(*ld
, *rd
) && eq_fn_sig(lf
, rf
) && eq_generics(lg
, rg
) && both(lb
, rb
, |l
, r
| eq_block(l
, r
))
386 TyAlias(box ast
::TyAlias
{
392 TyAlias(box ast
::TyAlias
{
399 eq_defaultness(*ld
, *rd
)
400 && eq_generics(lg
, rg
)
401 && over(lb
, rb
, eq_generic_bound
)
402 && both(lt
, rt
, |l
, r
| eq_ty(l
, r
))
404 (MacCall(l
), MacCall(r
)) => eq_mac_call(l
, r
),
409 pub fn eq_assoc_item_kind(l
: &AssocItemKind
, r
: &AssocItemKind
) -> bool
{
410 use AssocItemKind
::*;
412 (Const(ld
, lt
, le
), Const(rd
, rt
, re
)) => eq_defaultness(*ld
, *rd
) && eq_ty(lt
, rt
) && eq_expr_opt(le
, re
),
427 eq_defaultness(*ld
, *rd
) && eq_fn_sig(lf
, rf
) && eq_generics(lg
, rg
) && both(lb
, rb
, |l
, r
| eq_block(l
, r
))
430 TyAlias(box ast
::TyAlias
{
436 TyAlias(box ast
::TyAlias
{
443 eq_defaultness(*ld
, *rd
)
444 && eq_generics(lg
, rg
)
445 && over(lb
, rb
, eq_generic_bound
)
446 && both(lt
, rt
, |l
, r
| eq_ty(l
, r
))
448 (MacCall(l
), MacCall(r
)) => eq_mac_call(l
, r
),
453 pub fn eq_variant(l
: &Variant
, r
: &Variant
) -> bool
{
454 l
.is_placeholder
== r
.is_placeholder
455 && over(&l
.attrs
, &r
.attrs
, eq_attr
)
456 && eq_vis(&l
.vis
, &r
.vis
)
457 && eq_id(l
.ident
, r
.ident
)
458 && eq_variant_data(&l
.data
, &r
.data
)
459 && both(&l
.disr_expr
, &r
.disr_expr
, |l
, r
| eq_expr(&l
.value
, &r
.value
))
462 pub fn eq_variant_data(l
: &VariantData
, r
: &VariantData
) -> bool
{
465 (Unit(_
), Unit(_
)) => true,
466 (Struct(l
, _
), Struct(r
, _
)) | (Tuple(l
, _
), Tuple(r
, _
)) => over(l
, r
, eq_struct_field
),
471 pub fn eq_struct_field(l
: &FieldDef
, r
: &FieldDef
) -> bool
{
472 l
.is_placeholder
== r
.is_placeholder
473 && over(&l
.attrs
, &r
.attrs
, eq_attr
)
474 && eq_vis(&l
.vis
, &r
.vis
)
475 && both(&l
.ident
, &r
.ident
, |l
, r
| eq_id(*l
, *r
))
476 && eq_ty(&l
.ty
, &r
.ty
)
479 pub fn eq_fn_sig(l
: &FnSig
, r
: &FnSig
) -> bool
{
480 eq_fn_decl(&l
.decl
, &r
.decl
) && eq_fn_header(&l
.header
, &r
.header
)
483 pub fn eq_fn_header(l
: &FnHeader
, r
: &FnHeader
) -> bool
{
484 matches
!(l
.unsafety
, Unsafe
::No
) == matches
!(r
.unsafety
, Unsafe
::No
)
485 && l
.asyncness
.is_async() == r
.asyncness
.is_async()
486 && matches
!(l
.constness
, Const
::No
) == matches
!(r
.constness
, Const
::No
)
487 && eq_ext(&l
.ext
, &r
.ext
)
490 pub fn eq_generics(l
: &Generics
, r
: &Generics
) -> bool
{
491 over(&l
.params
, &r
.params
, eq_generic_param
)
492 && over(&l
.where_clause
.predicates
, &r
.where_clause
.predicates
, |l
, r
| {
493 eq_where_predicate(l
, r
)
497 pub fn eq_where_predicate(l
: &WherePredicate
, r
: &WherePredicate
) -> bool
{
498 use WherePredicate
::*;
500 (BoundPredicate(l
), BoundPredicate(r
)) => {
501 over(&l
.bound_generic_params
, &r
.bound_generic_params
, |l
, r
| {
502 eq_generic_param(l
, r
)
503 }) && eq_ty(&l
.bounded_ty
, &r
.bounded_ty
)
504 && over(&l
.bounds
, &r
.bounds
, eq_generic_bound
)
506 (RegionPredicate(l
), RegionPredicate(r
)) => {
507 eq_id(l
.lifetime
.ident
, r
.lifetime
.ident
) && over(&l
.bounds
, &r
.bounds
, eq_generic_bound
)
509 (EqPredicate(l
), EqPredicate(r
)) => eq_ty(&l
.lhs_ty
, &r
.lhs_ty
) && eq_ty(&l
.rhs_ty
, &r
.rhs_ty
),
514 pub fn eq_use_tree(l
: &UseTree
, r
: &UseTree
) -> bool
{
515 eq_path(&l
.prefix
, &r
.prefix
) && eq_use_tree_kind(&l
.kind
, &r
.kind
)
518 pub fn eq_anon_const(l
: &AnonConst
, r
: &AnonConst
) -> bool
{
519 eq_expr(&l
.value
, &r
.value
)
522 pub fn eq_use_tree_kind(l
: &UseTreeKind
, r
: &UseTreeKind
) -> bool
{
525 (Glob
, Glob
) => true,
526 (Simple(l
, _
, _
), Simple(r
, _
, _
)) => both(l
, r
, |l
, r
| eq_id(*l
, *r
)),
527 (Nested(l
), Nested(r
)) => over(l
, r
, |(l
, _
), (r
, _
)| eq_use_tree(l
, r
)),
532 pub fn eq_defaultness(l
: Defaultness
, r
: Defaultness
) -> bool
{
535 (Defaultness
::Final
, Defaultness
::Final
) | (Defaultness
::Default(_
), Defaultness
::Default(_
))
539 pub fn eq_vis(l
: &Visibility
, r
: &Visibility
) -> bool
{
540 use VisibilityKind
::*;
541 match (&l
.kind
, &r
.kind
) {
542 (Public
, Public
) | (Inherited
, Inherited
) | (Crate(_
), Crate(_
)) => true,
543 (Restricted { path: l, .. }
, Restricted { path: r, .. }
) => eq_path(l
, r
),
548 pub fn eq_fn_decl(l
: &FnDecl
, r
: &FnDecl
) -> bool
{
549 eq_fn_ret_ty(&l
.output
, &r
.output
)
550 && over(&l
.inputs
, &r
.inputs
, |l
, r
| {
551 l
.is_placeholder
== r
.is_placeholder
552 && eq_pat(&l
.pat
, &r
.pat
)
553 && eq_ty(&l
.ty
, &r
.ty
)
554 && over(&l
.attrs
, &r
.attrs
, eq_attr
)
558 pub fn eq_fn_ret_ty(l
: &FnRetTy
, r
: &FnRetTy
) -> bool
{
560 (FnRetTy
::Default(_
), FnRetTy
::Default(_
)) => true,
561 (FnRetTy
::Ty(l
), FnRetTy
::Ty(r
)) => eq_ty(l
, r
),
566 pub fn eq_ty(l
: &Ty
, r
: &Ty
) -> bool
{
568 match (&l
.kind
, &r
.kind
) {
569 (Paren(l
), _
) => eq_ty(l
, r
),
570 (_
, Paren(r
)) => eq_ty(l
, r
),
571 (Never
, Never
) | (Infer
, Infer
) | (ImplicitSelf
, ImplicitSelf
) | (Err
, Err
) | (CVarArgs
, CVarArgs
) => true,
572 (Slice(l
), Slice(r
)) => eq_ty(l
, r
),
573 (Array(le
, ls
), Array(re
, rs
)) => eq_ty(le
, re
) && eq_expr(&ls
.value
, &rs
.value
),
574 (Ptr(l
), Ptr(r
)) => l
.mutbl
== r
.mutbl
&& eq_ty(&l
.ty
, &r
.ty
),
575 (Rptr(ll
, l
), Rptr(rl
, r
)) => {
576 both(ll
, rl
, |l
, r
| eq_id(l
.ident
, r
.ident
)) && l
.mutbl
== r
.mutbl
&& eq_ty(&l
.ty
, &r
.ty
)
578 (BareFn(l
), BareFn(r
)) => {
579 l
.unsafety
== r
.unsafety
580 && eq_ext(&l
.ext
, &r
.ext
)
581 && over(&l
.generic_params
, &r
.generic_params
, eq_generic_param
)
582 && eq_fn_decl(&l
.decl
, &r
.decl
)
584 (Tup(l
), Tup(r
)) => over(l
, r
, |l
, r
| eq_ty(l
, r
)),
585 (Path(lq
, lp
), Path(rq
, rp
)) => both(lq
, rq
, eq_qself
) && eq_path(lp
, rp
),
586 (TraitObject(lg
, ls
), TraitObject(rg
, rs
)) => ls
== rs
&& over(lg
, rg
, eq_generic_bound
),
587 (ImplTrait(_
, lg
), ImplTrait(_
, rg
)) => over(lg
, rg
, eq_generic_bound
),
588 (Typeof(l
), Typeof(r
)) => eq_expr(&l
.value
, &r
.value
),
589 (MacCall(l
), MacCall(r
)) => eq_mac_call(l
, r
),
594 pub fn eq_ext(l
: &Extern
, r
: &Extern
) -> bool
{
597 (None
, None
) | (Implicit
, Implicit
) => true,
598 (Explicit(l
), Explicit(r
)) => eq_str_lit(l
, r
),
603 pub fn eq_str_lit(l
: &StrLit
, r
: &StrLit
) -> bool
{
604 l
.style
== r
.style
&& l
.symbol
== r
.symbol
&& l
.suffix
== r
.suffix
607 pub fn eq_poly_ref_trait(l
: &PolyTraitRef
, r
: &PolyTraitRef
) -> bool
{
608 eq_path(&l
.trait_ref
.path
, &r
.trait_ref
.path
)
609 && over(&l
.bound_generic_params
, &r
.bound_generic_params
, |l
, r
| {
610 eq_generic_param(l
, r
)
614 pub fn eq_generic_param(l
: &GenericParam
, r
: &GenericParam
) -> bool
{
615 use GenericParamKind
::*;
616 l
.is_placeholder
== r
.is_placeholder
617 && eq_id(l
.ident
, r
.ident
)
618 && over(&l
.bounds
, &r
.bounds
, eq_generic_bound
)
619 && match (&l
.kind
, &r
.kind
) {
620 (Lifetime
, Lifetime
) => true,
621 (Type { default: l }
, Type { default: r }
) => both(l
, r
, |l
, r
| eq_ty(l
, r
)),
633 ) => eq_ty(lt
, rt
) && both(ld
, rd
, eq_anon_const
),
636 && over(&l
.attrs
, &r
.attrs
, eq_attr
)
639 pub fn eq_generic_bound(l
: &GenericBound
, r
: &GenericBound
) -> bool
{
642 (Trait(ptr1
, tbm1
), Trait(ptr2
, tbm2
)) => tbm1
== tbm2
&& eq_poly_ref_trait(ptr1
, ptr2
),
643 (Outlives(l
), Outlives(r
)) => eq_id(l
.ident
, r
.ident
),
648 fn eq_term(l
: &Term
, r
: &Term
) -> bool
{
650 (Term
::Ty(l
), Term
::Ty(r
)) => eq_ty(l
, r
),
651 (Term
::Const(l
), Term
::Const(r
)) => eq_anon_const(l
, r
),
656 pub fn eq_assoc_constraint(l
: &AssocConstraint
, r
: &AssocConstraint
) -> bool
{
657 use AssocConstraintKind
::*;
658 eq_id(l
.ident
, r
.ident
)
659 && match (&l
.kind
, &r
.kind
) {
660 (Equality { term: l }
, Equality { term: r }
) => eq_term(l
, r
),
661 (Bound { bounds: l }
, Bound { bounds: r }
) => over(l
, r
, eq_generic_bound
),
666 pub fn eq_mac_call(l
: &MacCall
, r
: &MacCall
) -> bool
{
667 eq_path(&l
.path
, &r
.path
) && eq_mac_args(&l
.args
, &r
.args
)
670 pub fn eq_attr(l
: &Attribute
, r
: &Attribute
) -> bool
{
673 && match (&l
.kind
, &r
.kind
) {
674 (DocComment(l1
, l2
), DocComment(r1
, r2
)) => l1
== r1
&& l2
== r2
,
675 (Normal(l
, _
), Normal(r
, _
)) => eq_path(&l
.path
, &r
.path
) && eq_mac_args(&l
.args
, &r
.args
),
680 pub fn eq_mac_args(l
: &MacArgs
, r
: &MacArgs
) -> bool
{
683 (Empty
, Empty
) => true,
684 (Delimited(_
, ld
, lts
), Delimited(_
, rd
, rts
)) => ld
== rd
&& lts
.eq_unspanned(rts
),
685 (Eq(_
, lt
), Eq(_
, rt
)) => lt
.kind
== rt
.kind
,