xref: /third_party/rust/crates/syn/tests/common/eq.rs (revision fad3a1d3)
1#![allow(unused_macro_rules)]
2
3extern crate rustc_ast;
4extern crate rustc_data_structures;
5extern crate rustc_driver;
6extern crate rustc_span;
7extern crate thin_vec;
8
9use rustc_ast::ast::AngleBracketedArg;
10use rustc_ast::ast::AngleBracketedArgs;
11use rustc_ast::ast::AnonConst;
12use rustc_ast::ast::Arm;
13use rustc_ast::ast::AssocConstraint;
14use rustc_ast::ast::AssocConstraintKind;
15use rustc_ast::ast::AssocItemKind;
16use rustc_ast::ast::AttrArgs;
17use rustc_ast::ast::AttrArgsEq;
18use rustc_ast::ast::AttrId;
19use rustc_ast::ast::AttrItem;
20use rustc_ast::ast::AttrKind;
21use rustc_ast::ast::AttrStyle;
22use rustc_ast::ast::Attribute;
23use rustc_ast::ast::BareFnTy;
24use rustc_ast::ast::BinOpKind;
25use rustc_ast::ast::BindingAnnotation;
26use rustc_ast::ast::Block;
27use rustc_ast::ast::BlockCheckMode;
28use rustc_ast::ast::BorrowKind;
29use rustc_ast::ast::BoundConstness;
30use rustc_ast::ast::BoundPolarity;
31use rustc_ast::ast::ByRef;
32use rustc_ast::ast::CaptureBy;
33use rustc_ast::ast::Closure;
34use rustc_ast::ast::ClosureBinder;
35use rustc_ast::ast::Const;
36use rustc_ast::ast::ConstItem;
37use rustc_ast::ast::CoroutineKind;
38use rustc_ast::ast::Crate;
39use rustc_ast::ast::Defaultness;
40use rustc_ast::ast::DelimArgs;
41use rustc_ast::ast::EnumDef;
42use rustc_ast::ast::Expr;
43use rustc_ast::ast::ExprField;
44use rustc_ast::ast::ExprKind;
45use rustc_ast::ast::Extern;
46use rustc_ast::ast::FieldDef;
47use rustc_ast::ast::FloatTy;
48use rustc_ast::ast::Fn;
49use rustc_ast::ast::FnDecl;
50use rustc_ast::ast::FnHeader;
51use rustc_ast::ast::FnRetTy;
52use rustc_ast::ast::FnSig;
53use rustc_ast::ast::ForLoopKind;
54use rustc_ast::ast::ForeignItemKind;
55use rustc_ast::ast::ForeignMod;
56use rustc_ast::ast::FormatAlignment;
57use rustc_ast::ast::FormatArgPosition;
58use rustc_ast::ast::FormatArgPositionKind;
59use rustc_ast::ast::FormatArgs;
60use rustc_ast::ast::FormatArgsPiece;
61use rustc_ast::ast::FormatArgument;
62use rustc_ast::ast::FormatArgumentKind;
63use rustc_ast::ast::FormatArguments;
64use rustc_ast::ast::FormatCount;
65use rustc_ast::ast::FormatDebugHex;
66use rustc_ast::ast::FormatOptions;
67use rustc_ast::ast::FormatPlaceholder;
68use rustc_ast::ast::FormatSign;
69use rustc_ast::ast::FormatTrait;
70use rustc_ast::ast::GenBlockKind;
71use rustc_ast::ast::GenericArg;
72use rustc_ast::ast::GenericArgs;
73use rustc_ast::ast::GenericBound;
74use rustc_ast::ast::GenericParam;
75use rustc_ast::ast::GenericParamKind;
76use rustc_ast::ast::Generics;
77use rustc_ast::ast::Impl;
78use rustc_ast::ast::ImplPolarity;
79use rustc_ast::ast::Inline;
80use rustc_ast::ast::InlineAsm;
81use rustc_ast::ast::InlineAsmOperand;
82use rustc_ast::ast::InlineAsmOptions;
83use rustc_ast::ast::InlineAsmRegOrRegClass;
84use rustc_ast::ast::InlineAsmSym;
85use rustc_ast::ast::InlineAsmTemplatePiece;
86use rustc_ast::ast::IntTy;
87use rustc_ast::ast::IsAuto;
88use rustc_ast::ast::Item;
89use rustc_ast::ast::ItemKind;
90use rustc_ast::ast::Label;
91use rustc_ast::ast::Lifetime;
92use rustc_ast::ast::LitFloatType;
93use rustc_ast::ast::LitIntType;
94use rustc_ast::ast::LitKind;
95use rustc_ast::ast::Local;
96use rustc_ast::ast::LocalKind;
97use rustc_ast::ast::MacCall;
98use rustc_ast::ast::MacCallStmt;
99use rustc_ast::ast::MacStmtStyle;
100use rustc_ast::ast::MacroDef;
101use rustc_ast::ast::MetaItemLit;
102use rustc_ast::ast::MethodCall;
103use rustc_ast::ast::ModKind;
104use rustc_ast::ast::ModSpans;
105use rustc_ast::ast::Movability;
106use rustc_ast::ast::MutTy;
107use rustc_ast::ast::Mutability;
108use rustc_ast::ast::NodeId;
109use rustc_ast::ast::NormalAttr;
110use rustc_ast::ast::Param;
111use rustc_ast::ast::ParenthesizedArgs;
112use rustc_ast::ast::Pat;
113use rustc_ast::ast::PatField;
114use rustc_ast::ast::PatFieldsRest;
115use rustc_ast::ast::PatKind;
116use rustc_ast::ast::Path;
117use rustc_ast::ast::PathSegment;
118use rustc_ast::ast::PolyTraitRef;
119use rustc_ast::ast::QSelf;
120use rustc_ast::ast::RangeEnd;
121use rustc_ast::ast::RangeLimits;
122use rustc_ast::ast::RangeSyntax;
123use rustc_ast::ast::StaticItem;
124use rustc_ast::ast::Stmt;
125use rustc_ast::ast::StmtKind;
126use rustc_ast::ast::StrLit;
127use rustc_ast::ast::StrStyle;
128use rustc_ast::ast::StructExpr;
129use rustc_ast::ast::StructRest;
130use rustc_ast::ast::Term;
131use rustc_ast::ast::Trait;
132use rustc_ast::ast::TraitBoundModifiers;
133use rustc_ast::ast::TraitObjectSyntax;
134use rustc_ast::ast::TraitRef;
135use rustc_ast::ast::Ty;
136use rustc_ast::ast::TyAlias;
137use rustc_ast::ast::TyAliasWhereClause;
138use rustc_ast::ast::TyKind;
139use rustc_ast::ast::UintTy;
140use rustc_ast::ast::UnOp;
141use rustc_ast::ast::Unsafe;
142use rustc_ast::ast::UnsafeSource;
143use rustc_ast::ast::UseTree;
144use rustc_ast::ast::UseTreeKind;
145use rustc_ast::ast::Variant;
146use rustc_ast::ast::VariantData;
147use rustc_ast::ast::Visibility;
148use rustc_ast::ast::VisibilityKind;
149use rustc_ast::ast::WhereBoundPredicate;
150use rustc_ast::ast::WhereClause;
151use rustc_ast::ast::WhereEqPredicate;
152use rustc_ast::ast::WherePredicate;
153use rustc_ast::ast::WhereRegionPredicate;
154use rustc_ast::ptr::P;
155use rustc_ast::token::{self, CommentKind, Delimiter, Lit, Nonterminal, Token, TokenKind};
156use rustc_ast::tokenstream::{
157    AttrTokenStream, AttrTokenTree, AttributesData, DelimSpacing, DelimSpan, LazyAttrTokenStream,
158    Spacing, TokenStream, TokenTree,
159};
160use rustc_data_structures::sync::Lrc;
161use rustc_span::source_map::Spanned;
162use rustc_span::symbol::{sym, Ident};
163use rustc_span::{ErrorGuaranteed, Span, Symbol, SyntaxContext, DUMMY_SP};
164use std::collections::HashMap;
165use std::hash::{BuildHasher, Hash};
166use thin_vec::ThinVec;
167
168pub trait SpanlessEq {
169    fn eq(&self, other: &Self) -> bool;
170}
171
172impl<T: ?Sized + SpanlessEq> SpanlessEq for Box<T> {
173    fn eq(&self, other: &Self) -> bool {
174        SpanlessEq::eq(&**self, &**other)
175    }
176}
177
178impl<T: ?Sized + SpanlessEq> SpanlessEq for P<T> {
179    fn eq(&self, other: &Self) -> bool {
180        SpanlessEq::eq(&**self, &**other)
181    }
182}
183
184impl<T: ?Sized + SpanlessEq> SpanlessEq for Lrc<T> {
185    fn eq(&self, other: &Self) -> bool {
186        SpanlessEq::eq(&**self, &**other)
187    }
188}
189
190impl<T: SpanlessEq> SpanlessEq for Option<T> {
191    fn eq(&self, other: &Self) -> bool {
192        match (self, other) {
193            (None, None) => true,
194            (Some(this), Some(other)) => SpanlessEq::eq(this, other),
195            _ => false,
196        }
197    }
198}
199
200impl<T: SpanlessEq, E: SpanlessEq> SpanlessEq for Result<T, E> {
201    fn eq(&self, other: &Self) -> bool {
202        match (self, other) {
203            (Ok(this), Ok(other)) => SpanlessEq::eq(this, other),
204            (Err(this), Err(other)) => SpanlessEq::eq(this, other),
205            _ => false,
206        }
207    }
208}
209
210impl<T: SpanlessEq> SpanlessEq for [T] {
211    fn eq(&self, other: &Self) -> bool {
212        self.len() == other.len() && self.iter().zip(other).all(|(a, b)| SpanlessEq::eq(a, b))
213    }
214}
215
216impl<T: SpanlessEq> SpanlessEq for Vec<T> {
217    fn eq(&self, other: &Self) -> bool {
218        <[T] as SpanlessEq>::eq(self, other)
219    }
220}
221
222impl<T: SpanlessEq> SpanlessEq for ThinVec<T> {
223    fn eq(&self, other: &Self) -> bool {
224        self.len() == other.len()
225            && self
226                .iter()
227                .zip(other.iter())
228                .all(|(a, b)| SpanlessEq::eq(a, b))
229    }
230}
231
232impl<K: Eq + Hash, V: SpanlessEq, S: BuildHasher> SpanlessEq for HashMap<K, V, S> {
233    fn eq(&self, other: &Self) -> bool {
234        self.len() == other.len()
235            && self.iter().all(|(key, this_v)| {
236                other
237                    .get(key)
238                    .map_or(false, |other_v| SpanlessEq::eq(this_v, other_v))
239            })
240    }
241}
242
243impl<T: SpanlessEq> SpanlessEq for Spanned<T> {
244    fn eq(&self, other: &Self) -> bool {
245        SpanlessEq::eq(&self.node, &other.node)
246    }
247}
248
249impl<A: SpanlessEq, B: SpanlessEq> SpanlessEq for (A, B) {
250    fn eq(&self, other: &Self) -> bool {
251        SpanlessEq::eq(&self.0, &other.0) && SpanlessEq::eq(&self.1, &other.1)
252    }
253}
254
255impl<A: SpanlessEq, B: SpanlessEq, C: SpanlessEq> SpanlessEq for (A, B, C) {
256    fn eq(&self, other: &Self) -> bool {
257        SpanlessEq::eq(&self.0, &other.0)
258            && SpanlessEq::eq(&self.1, &other.1)
259            && SpanlessEq::eq(&self.2, &other.2)
260    }
261}
262
263macro_rules! spanless_eq_true {
264    ($name:ty) => {
265        impl SpanlessEq for $name {
266            fn eq(&self, _other: &Self) -> bool {
267                true
268            }
269        }
270    };
271}
272
273spanless_eq_true!(Span);
274spanless_eq_true!(DelimSpan);
275spanless_eq_true!(AttrId);
276spanless_eq_true!(NodeId);
277spanless_eq_true!(SyntaxContext);
278spanless_eq_true!(Spacing);
279
280macro_rules! spanless_eq_partial_eq {
281    ($name:ty) => {
282        impl SpanlessEq for $name {
283            fn eq(&self, other: &Self) -> bool {
284                PartialEq::eq(self, other)
285            }
286        }
287    };
288}
289
290spanless_eq_partial_eq!(bool);
291spanless_eq_partial_eq!(u8);
292spanless_eq_partial_eq!(u16);
293spanless_eq_partial_eq!(u32);
294spanless_eq_partial_eq!(u128);
295spanless_eq_partial_eq!(usize);
296spanless_eq_partial_eq!(char);
297spanless_eq_partial_eq!(String);
298spanless_eq_partial_eq!(Symbol);
299spanless_eq_partial_eq!(CommentKind);
300spanless_eq_partial_eq!(Delimiter);
301spanless_eq_partial_eq!(InlineAsmOptions);
302spanless_eq_partial_eq!(token::LitKind);
303spanless_eq_partial_eq!(ErrorGuaranteed);
304
305macro_rules! spanless_eq_struct {
306    {
307        $($name:ident)::+ $(<$param:ident>)?
308        $([$field:tt $this:ident $other:ident])*
309        $(![$ignore:tt])*;
310    } => {
311        impl $(<$param: SpanlessEq>)* SpanlessEq for $($name)::+ $(<$param>)* {
312            fn eq(&self, other: &Self) -> bool {
313                let $($name)::+ { $($field: $this,)* $($ignore: _,)* } = self;
314                let $($name)::+ { $($field: $other,)* $($ignore: _,)* } = other;
315                true $(&& SpanlessEq::eq($this, $other))*
316            }
317        }
318    };
319
320    {
321        $($name:ident)::+ $(<$param:ident>)?
322        $([$field:tt $this:ident $other:ident])*
323        $(![$ignore:tt])*;
324        !$next:tt
325        $($rest:tt)*
326    } => {
327        spanless_eq_struct! {
328            $($name)::+ $(<$param>)*
329            $([$field $this $other])*
330            $(![$ignore])*
331            ![$next];
332            $($rest)*
333        }
334    };
335
336    {
337        $($name:ident)::+ $(<$param:ident>)?
338        $([$field:tt $this:ident $other:ident])*
339        $(![$ignore:tt])*;
340        $next:tt
341        $($rest:tt)*
342    } => {
343        spanless_eq_struct! {
344            $($name)::+ $(<$param>)*
345            $([$field $this $other])*
346            [$next this other]
347            $(![$ignore])*;
348            $($rest)*
349        }
350    };
351}
352
353macro_rules! spanless_eq_enum {
354    {
355        $($name:ident)::+;
356        $([$($variant:ident)::+; $([$field:tt $this:ident $other:ident])* $(![$ignore:tt])*])*
357    } => {
358        impl SpanlessEq for $($name)::+ {
359            fn eq(&self, other: &Self) -> bool {
360                match self {
361                    $(
362                        $($variant)::+ { .. } => {}
363                    )*
364                }
365                #[allow(unreachable_patterns)]
366                match (self, other) {
367                    $(
368                        (
369                            $($variant)::+ { $($field: $this,)* $($ignore: _,)* },
370                            $($variant)::+ { $($field: $other,)* $($ignore: _,)* },
371                        ) => {
372                            true $(&& SpanlessEq::eq($this, $other))*
373                        }
374                    )*
375                    _ => false,
376                }
377            }
378        }
379    };
380
381    {
382        $($name:ident)::+;
383        $([$($variant:ident)::+; $($fields:tt)*])*
384        $next:ident [$([$($named:tt)*])* $(![$ignore:tt])*] (!$i:tt $($field:tt)*)
385        $($rest:tt)*
386    } => {
387        spanless_eq_enum! {
388            $($name)::+;
389            $([$($variant)::+; $($fields)*])*
390            $next [$([$($named)*])* $(![$ignore])* ![$i]] ($($field)*)
391            $($rest)*
392        }
393    };
394
395    {
396        $($name:ident)::+;
397        $([$($variant:ident)::+; $($fields:tt)*])*
398        $next:ident [$([$($named:tt)*])* $(![$ignore:tt])*] ($i:tt $($field:tt)*)
399        $($rest:tt)*
400    } => {
401        spanless_eq_enum! {
402            $($name)::+;
403            $([$($variant)::+; $($fields)*])*
404            $next [$([$($named)*])* [$i this other] $(![$ignore])*] ($($field)*)
405            $($rest)*
406        }
407    };
408
409    {
410        $($name:ident)::+;
411        $([$($variant:ident)::+; $($fields:tt)*])*
412        $next:ident [$($named:tt)*] ()
413        $($rest:tt)*
414    } => {
415        spanless_eq_enum! {
416            $($name)::+;
417            $([$($variant)::+; $($fields)*])*
418            [$($name)::+::$next; $($named)*]
419            $($rest)*
420        }
421    };
422
423    {
424        $($name:ident)::+;
425        $([$($variant:ident)::+; $($fields:tt)*])*
426        $next:ident ($($field:tt)*)
427        $($rest:tt)*
428    } => {
429        spanless_eq_enum! {
430            $($name)::+;
431            $([$($variant)::+; $($fields)*])*
432            $next [] ($($field)*)
433            $($rest)*
434        }
435    };
436
437    {
438        $($name:ident)::+;
439        $([$($variant:ident)::+; $($fields:tt)*])*
440        $next:ident
441        $($rest:tt)*
442    } => {
443        spanless_eq_enum! {
444            $($name)::+;
445            $([$($variant)::+; $($fields)*])*
446            [$($name)::+::$next;]
447            $($rest)*
448        }
449    };
450}
451
452spanless_eq_struct!(AngleBracketedArgs; span args);
453spanless_eq_struct!(AnonConst; id value);
454spanless_eq_struct!(Arm; attrs pat guard body span id is_placeholder);
455spanless_eq_struct!(AssocConstraint; id ident gen_args kind span);
456spanless_eq_struct!(AttrItem; path args tokens);
457spanless_eq_struct!(AttrTokenStream; 0);
458spanless_eq_struct!(Attribute; kind id style span);
459spanless_eq_struct!(AttributesData; attrs tokens);
460spanless_eq_struct!(BareFnTy; unsafety ext generic_params decl decl_span);
461spanless_eq_struct!(BindingAnnotation; 0 1);
462spanless_eq_struct!(Block; stmts id rules span tokens could_be_bare_literal);
463spanless_eq_struct!(Closure; binder capture_clause constness coroutine_kind movability fn_decl body !fn_decl_span !fn_arg_span);
464spanless_eq_struct!(ConstItem; defaultness generics ty expr);
465spanless_eq_struct!(Crate; attrs items spans id is_placeholder);
466spanless_eq_struct!(DelimArgs; dspan delim tokens);
467spanless_eq_struct!(DelimSpacing; open close);
468spanless_eq_struct!(EnumDef; variants);
469spanless_eq_struct!(Expr; id kind span attrs !tokens);
470spanless_eq_struct!(ExprField; attrs id span ident expr is_shorthand is_placeholder);
471spanless_eq_struct!(FieldDef; attrs id span vis ident ty is_placeholder);
472spanless_eq_struct!(Fn; defaultness generics sig body);
473spanless_eq_struct!(FnDecl; inputs output);
474spanless_eq_struct!(FnHeader; constness coroutine_kind unsafety ext);
475spanless_eq_struct!(FnSig; header decl span);
476spanless_eq_struct!(ForeignMod; unsafety abi items);
477spanless_eq_struct!(FormatArgPosition; index kind span);
478spanless_eq_struct!(FormatArgs; span template arguments);
479spanless_eq_struct!(FormatArgument; kind expr);
480spanless_eq_struct!(FormatOptions; width precision alignment fill sign alternate zero_pad debug_hex);
481spanless_eq_struct!(FormatPlaceholder; argument span format_trait format_options);
482spanless_eq_struct!(GenericParam; id ident attrs bounds is_placeholder kind !colon_span);
483spanless_eq_struct!(Generics; params where_clause span);
484spanless_eq_struct!(Impl; defaultness unsafety generics constness polarity of_trait self_ty items);
485spanless_eq_struct!(InlineAsm; template template_strs operands clobber_abis options line_spans);
486spanless_eq_struct!(InlineAsmSym; id qself path);
487spanless_eq_struct!(Item<K>; attrs id span vis ident kind !tokens);
488spanless_eq_struct!(Label; ident);
489spanless_eq_struct!(Lifetime; id ident);
490spanless_eq_struct!(Lit; kind symbol suffix);
491spanless_eq_struct!(Local; pat ty kind id span attrs !tokens);
492spanless_eq_struct!(MacCall; path args);
493spanless_eq_struct!(MacCallStmt; mac style attrs tokens);
494spanless_eq_struct!(MacroDef; body macro_rules);
495spanless_eq_struct!(MetaItemLit; symbol suffix kind span);
496spanless_eq_struct!(MethodCall; seg receiver args !span);
497spanless_eq_struct!(ModSpans; !inner_span !inject_use_span);
498spanless_eq_struct!(MutTy; ty mutbl);
499spanless_eq_struct!(NormalAttr; item tokens);
500spanless_eq_struct!(ParenthesizedArgs; span inputs inputs_span output);
501spanless_eq_struct!(Pat; id kind span tokens);
502spanless_eq_struct!(PatField; ident pat is_shorthand attrs id span is_placeholder);
503spanless_eq_struct!(Path; span segments tokens);
504spanless_eq_struct!(PathSegment; ident id args);
505spanless_eq_struct!(PolyTraitRef; bound_generic_params trait_ref span);
506spanless_eq_struct!(QSelf; ty path_span position);
507spanless_eq_struct!(StaticItem; ty mutability expr);
508spanless_eq_struct!(Stmt; id kind span);
509spanless_eq_struct!(StrLit; symbol suffix symbol_unescaped style span);
510spanless_eq_struct!(StructExpr; qself path fields rest);
511spanless_eq_struct!(Token; kind span);
512spanless_eq_struct!(Trait; unsafety is_auto generics bounds items);
513spanless_eq_struct!(TraitBoundModifiers; constness polarity);
514spanless_eq_struct!(TraitRef; path ref_id);
515spanless_eq_struct!(Ty; id kind span tokens);
516spanless_eq_struct!(TyAlias; defaultness generics where_clauses !where_predicates_split bounds ty);
517spanless_eq_struct!(TyAliasWhereClause; !0 1);
518spanless_eq_struct!(UseTree; prefix kind span);
519spanless_eq_struct!(Variant; attrs id span !vis ident data disr_expr is_placeholder);
520spanless_eq_struct!(Visibility; kind span tokens);
521spanless_eq_struct!(WhereBoundPredicate; span bound_generic_params bounded_ty bounds);
522spanless_eq_struct!(WhereClause; has_where_token predicates span);
523spanless_eq_struct!(WhereEqPredicate; span lhs_ty rhs_ty);
524spanless_eq_struct!(WhereRegionPredicate; span lifetime bounds);
525spanless_eq_enum!(AngleBracketedArg; Arg(0) Constraint(0));
526spanless_eq_enum!(AssocConstraintKind; Equality(term) Bound(bounds));
527spanless_eq_enum!(AssocItemKind; Const(0) Fn(0) Type(0) MacCall(0));
528spanless_eq_enum!(AttrArgs; Empty Delimited(0) Eq(0 1));
529spanless_eq_enum!(AttrArgsEq; Ast(0) Hir(0));
530spanless_eq_enum!(AttrStyle; Outer Inner);
531spanless_eq_enum!(AttrTokenTree; Token(0 1) Delimited(0 1 2 3) Attributes(0));
532spanless_eq_enum!(BinOpKind; Add Sub Mul Div Rem And Or BitXor BitAnd BitOr Shl Shr Eq Lt Le Ne Ge Gt);
533spanless_eq_enum!(BlockCheckMode; Default Unsafe(0));
534spanless_eq_enum!(BorrowKind; Ref Raw);
535spanless_eq_enum!(BoundConstness; Never Always(0) Maybe(0));
536spanless_eq_enum!(BoundPolarity; Positive Negative(0) Maybe(0));
537spanless_eq_enum!(ByRef; Yes No);
538spanless_eq_enum!(CaptureBy; Value(move_kw) Ref);
539spanless_eq_enum!(ClosureBinder; NotPresent For(span generic_params));
540spanless_eq_enum!(Const; Yes(0) No);
541spanless_eq_enum!(Defaultness; Default(0) Final);
542spanless_eq_enum!(Extern; None Implicit(0) Explicit(0 1));
543spanless_eq_enum!(FloatTy; F32 F64);
544spanless_eq_enum!(FnRetTy; Default(0) Ty(0));
545spanless_eq_enum!(ForLoopKind; For ForAwait);
546spanless_eq_enum!(ForeignItemKind; Static(0 1 2) Fn(0) TyAlias(0) MacCall(0));
547spanless_eq_enum!(FormatAlignment; Left Right Center);
548spanless_eq_enum!(FormatArgPositionKind; Implicit Number Named);
549spanless_eq_enum!(FormatArgsPiece; Literal(0) Placeholder(0));
550spanless_eq_enum!(FormatArgumentKind; Normal Named(0) Captured(0));
551spanless_eq_enum!(FormatCount; Literal(0) Argument(0));
552spanless_eq_enum!(FormatDebugHex; Lower Upper);
553spanless_eq_enum!(FormatSign; Plus Minus);
554spanless_eq_enum!(FormatTrait; Display Debug LowerExp UpperExp Octal Pointer Binary LowerHex UpperHex);
555spanless_eq_enum!(GenBlockKind; Async Gen AsyncGen);
556spanless_eq_enum!(GenericArg; Lifetime(0) Type(0) Const(0));
557spanless_eq_enum!(GenericArgs; AngleBracketed(0) Parenthesized(0));
558spanless_eq_enum!(GenericBound; Trait(0 1) Outlives(0));
559spanless_eq_enum!(GenericParamKind; Lifetime Type(default) Const(ty kw_span default));
560spanless_eq_enum!(ImplPolarity; Positive Negative(0));
561spanless_eq_enum!(Inline; Yes No);
562spanless_eq_enum!(InlineAsmRegOrRegClass; Reg(0) RegClass(0));
563spanless_eq_enum!(InlineAsmTemplatePiece; String(0) Placeholder(operand_idx modifier span));
564spanless_eq_enum!(IntTy; Isize I8 I16 I32 I64 I128);
565spanless_eq_enum!(IsAuto; Yes No);
566spanless_eq_enum!(LitFloatType; Suffixed(0) Unsuffixed);
567spanless_eq_enum!(LitIntType; Signed(0) Unsigned(0) Unsuffixed);
568spanless_eq_enum!(LocalKind; Decl Init(0) InitElse(0 1));
569spanless_eq_enum!(MacStmtStyle; Semicolon Braces NoBraces);
570spanless_eq_enum!(ModKind; Loaded(0 1 2) Unloaded);
571spanless_eq_enum!(Movability; Static Movable);
572spanless_eq_enum!(Mutability; Mut Not);
573spanless_eq_enum!(PatFieldsRest; Rest None);
574spanless_eq_enum!(RangeEnd; Included(0) Excluded);
575spanless_eq_enum!(RangeLimits; HalfOpen Closed);
576spanless_eq_enum!(StmtKind; Local(0) Item(0) Expr(0) Semi(0) Empty MacCall(0));
577spanless_eq_enum!(StrStyle; Cooked Raw(0));
578spanless_eq_enum!(StructRest; Base(0) Rest(0) None);
579spanless_eq_enum!(Term; Ty(0) Const(0));
580spanless_eq_enum!(TokenTree; Token(0 1) Delimited(0 1 2 3));
581spanless_eq_enum!(TraitObjectSyntax; Dyn DynStar None);
582spanless_eq_enum!(UintTy; Usize U8 U16 U32 U64 U128);
583spanless_eq_enum!(UnOp; Deref Not Neg);
584spanless_eq_enum!(Unsafe; Yes(0) No);
585spanless_eq_enum!(UnsafeSource; CompilerGenerated UserProvided);
586spanless_eq_enum!(UseTreeKind; Simple(0) Nested(0) Glob);
587spanless_eq_enum!(VariantData; Struct(fields recovered) Tuple(0 1) Unit(0));
588spanless_eq_enum!(VisibilityKind; Public Restricted(path id shorthand) Inherited);
589spanless_eq_enum!(WherePredicate; BoundPredicate(0) RegionPredicate(0) EqPredicate(0));
590spanless_eq_enum!(CoroutineKind; Async(span closure_id return_impl_trait_id)
591    Gen(span closure_id return_impl_trait_id)
592    AsyncGen(span closure_id return_impl_trait_id));
593spanless_eq_enum!(ExprKind; Array(0) ConstBlock(0) Call(0 1) MethodCall(0)
594    Tup(0) Binary(0 1 2) Unary(0 1) Lit(0) Cast(0 1) Type(0 1) Let(0 1 2 3)
595    If(0 1 2) While(0 1 2) ForLoop(pat iter body label kind) Loop(0 1 2)
596    Match(0 1) Closure(0) Block(0 1) Gen(0 1 2) Await(0 1) TryBlock(0)
597    Assign(0 1 2) AssignOp(0 1 2) Field(0 1) Index(0 1 2) Underscore
598    Range(0 1 2) Path(0 1) AddrOf(0 1 2) Break(0 1) Continue(0) Ret(0)
599    InlineAsm(0) OffsetOf(0 1) MacCall(0) Struct(0) Repeat(0 1) Paren(0) Try(0)
600    Yield(0) Yeet(0) Become(0) IncludedBytes(0) FormatArgs(0) Err);
601spanless_eq_enum!(InlineAsmOperand; In(reg expr) Out(reg late expr)
602    InOut(reg late expr) SplitInOut(reg late in_expr out_expr) Const(anon_const)
603    Sym(sym));
604spanless_eq_enum!(ItemKind; ExternCrate(0) Use(0) Static(0) Const(0) Fn(0)
605    Mod(0 1) ForeignMod(0) GlobalAsm(0) TyAlias(0) Enum(0 1) Struct(0 1)
606    Union(0 1) Trait(0) TraitAlias(0 1) Impl(0) MacCall(0) MacroDef(0));
607spanless_eq_enum!(LitKind; Str(0 1) ByteStr(0 1) CStr(0 1) Byte(0) Char(0)
608    Int(0 1) Float(0 1) Bool(0) Err);
609spanless_eq_enum!(PatKind; Wild Ident(0 1 2) Struct(0 1 2 3) TupleStruct(0 1 2)
610    Or(0) Path(0 1) Tuple(0) Box(0) Ref(0 1) Lit(0) Range(0 1 2) Slice(0) Rest
611    Never Paren(0) MacCall(0));
612spanless_eq_enum!(TyKind; Slice(0) Array(0 1) Ptr(0) Ref(0 1) BareFn(0) Never
613    Tup(0) AnonStruct(0) AnonUnion(0) Path(0 1) TraitObject(0 1) ImplTrait(0 1)
614    Paren(0) Typeof(0) Infer ImplicitSelf MacCall(0) Err CVarArgs);
615
616impl SpanlessEq for Ident {
617    fn eq(&self, other: &Self) -> bool {
618        self.as_str() == other.as_str()
619    }
620}
621
622impl SpanlessEq for RangeSyntax {
623    fn eq(&self, _other: &Self) -> bool {
624        match self {
625            RangeSyntax::DotDotDot | RangeSyntax::DotDotEq => true,
626        }
627    }
628}
629
630impl SpanlessEq for Param {
631    fn eq(&self, other: &Self) -> bool {
632        let Param {
633            attrs,
634            ty,
635            pat,
636            id,
637            span: _,
638            is_placeholder,
639        } = self;
640        let Param {
641            attrs: attrs2,
642            ty: ty2,
643            pat: pat2,
644            id: id2,
645            span: _,
646            is_placeholder: is_placeholder2,
647        } = other;
648        SpanlessEq::eq(id, id2)
649            && SpanlessEq::eq(is_placeholder, is_placeholder2)
650            && (matches!(ty.kind, TyKind::Err)
651                || matches!(ty2.kind, TyKind::Err)
652                || SpanlessEq::eq(attrs, attrs2)
653                    && SpanlessEq::eq(ty, ty2)
654                    && SpanlessEq::eq(pat, pat2))
655    }
656}
657
658impl SpanlessEq for TokenKind {
659    fn eq(&self, other: &Self) -> bool {
660        match (self, other) {
661            (TokenKind::Literal(this), TokenKind::Literal(other)) => SpanlessEq::eq(this, other),
662            (TokenKind::DotDotEq | TokenKind::DotDotDot, _) => match other {
663                TokenKind::DotDotEq | TokenKind::DotDotDot => true,
664                _ => false,
665            },
666            (TokenKind::Interpolated(this), TokenKind::Interpolated(other)) => {
667                let (this, this_span) = this.as_ref();
668                let (other, other_span) = other.as_ref();
669                SpanlessEq::eq(this_span, other_span)
670                    && match (this, other) {
671                        (Nonterminal::NtExpr(this), Nonterminal::NtExpr(other)) => {
672                            SpanlessEq::eq(this, other)
673                        }
674                        _ => this == other,
675                    }
676            }
677            _ => self == other,
678        }
679    }
680}
681
682impl SpanlessEq for TokenStream {
683    fn eq(&self, other: &Self) -> bool {
684        let mut this_trees = self.trees();
685        let mut other_trees = other.trees();
686        loop {
687            let this = match this_trees.next() {
688                None => return other_trees.next().is_none(),
689                Some(tree) => tree,
690            };
691            let other = match other_trees.next() {
692                None => return false,
693                Some(tree) => tree,
694            };
695            if SpanlessEq::eq(this, other) {
696                continue;
697            }
698            if let (TokenTree::Token(this, _), TokenTree::Token(other, _)) = (this, other) {
699                if match (&this.kind, &other.kind) {
700                    (TokenKind::Literal(this), TokenKind::Literal(other)) => {
701                        SpanlessEq::eq(this, other)
702                    }
703                    (TokenKind::DocComment(_kind, style, symbol), TokenKind::Pound) => {
704                        doc_comment(*style, *symbol, &mut other_trees)
705                    }
706                    (TokenKind::Pound, TokenKind::DocComment(_kind, style, symbol)) => {
707                        doc_comment(*style, *symbol, &mut this_trees)
708                    }
709                    _ => false,
710                } {
711                    continue;
712                }
713            }
714            return false;
715        }
716    }
717}
718
719fn doc_comment<'a>(
720    style: AttrStyle,
721    unescaped: Symbol,
722    trees: &mut impl Iterator<Item = &'a TokenTree>,
723) -> bool {
724    if match style {
725        AttrStyle::Outer => false,
726        AttrStyle::Inner => true,
727    } {
728        match trees.next() {
729            Some(TokenTree::Token(
730                Token {
731                    kind: TokenKind::Not,
732                    span: _,
733                },
734                _spacing,
735            )) => {}
736            _ => return false,
737        }
738    }
739    let stream = match trees.next() {
740        Some(TokenTree::Delimited(_span, _spacing, Delimiter::Bracket, stream)) => stream,
741        _ => return false,
742    };
743    let mut trees = stream.trees();
744    match trees.next() {
745        Some(TokenTree::Token(
746            Token {
747                kind: TokenKind::Ident(symbol, false),
748                span: _,
749            },
750            _spacing,
751        )) if *symbol == sym::doc => {}
752        _ => return false,
753    }
754    match trees.next() {
755        Some(TokenTree::Token(
756            Token {
757                kind: TokenKind::Eq,
758                span: _,
759            },
760            _spacing,
761        )) => {}
762        _ => return false,
763    }
764    match trees.next() {
765        Some(TokenTree::Token(token, _spacing)) => {
766            is_escaped_literal_token(token, unescaped) && trees.next().is_none()
767        }
768        _ => false,
769    }
770}
771
772fn is_escaped_literal_token(token: &Token, unescaped: Symbol) -> bool {
773    match token {
774        Token {
775            kind: TokenKind::Literal(lit),
776            span: _,
777        } => match MetaItemLit::from_token_lit(*lit, DUMMY_SP) {
778            Ok(lit) => is_escaped_literal_meta_item_lit(&lit, unescaped),
779            Err(_) => false,
780        },
781        Token {
782            kind: TokenKind::Interpolated(nonterminal),
783            span: _,
784        } => match &nonterminal.0 {
785            Nonterminal::NtExpr(expr) => match &expr.kind {
786                ExprKind::Lit(lit) => is_escaped_lit(lit, unescaped),
787                _ => false,
788            },
789            _ => false,
790        },
791        _ => false,
792    }
793}
794
795fn is_escaped_literal_attr_args(value: &AttrArgsEq, unescaped: Symbol) -> bool {
796    match value {
797        AttrArgsEq::Ast(expr) => match &expr.kind {
798            ExprKind::Lit(lit) => is_escaped_lit(lit, unescaped),
799            _ => false,
800        },
801        AttrArgsEq::Hir(lit) => is_escaped_literal_meta_item_lit(lit, unescaped),
802    }
803}
804
805fn is_escaped_literal_meta_item_lit(lit: &MetaItemLit, unescaped: Symbol) -> bool {
806    match lit {
807        MetaItemLit {
808            symbol: _,
809            suffix: None,
810            kind,
811            span: _,
812        } => is_escaped_lit_kind(kind, unescaped),
813        _ => false,
814    }
815}
816
817fn is_escaped_lit(lit: &Lit, unescaped: Symbol) -> bool {
818    match lit {
819        Lit {
820            kind: token::LitKind::Str,
821            symbol: _,
822            suffix: None,
823        } => match LitKind::from_token_lit(*lit) {
824            Ok(lit_kind) => is_escaped_lit_kind(&lit_kind, unescaped),
825            _ => false,
826        },
827        _ => false,
828    }
829}
830
831fn is_escaped_lit_kind(kind: &LitKind, unescaped: Symbol) -> bool {
832    match kind {
833        LitKind::Str(symbol, StrStyle::Cooked) => {
834            symbol.as_str().replace('\r', "") == unescaped.as_str().replace('\r', "")
835        }
836        _ => false,
837    }
838}
839
840impl SpanlessEq for LazyAttrTokenStream {
841    fn eq(&self, other: &Self) -> bool {
842        let this = self.to_attr_token_stream();
843        let other = other.to_attr_token_stream();
844        SpanlessEq::eq(&this, &other)
845    }
846}
847
848impl SpanlessEq for AttrKind {
849    fn eq(&self, other: &Self) -> bool {
850        match (self, other) {
851            (AttrKind::Normal(normal), AttrKind::Normal(normal2)) => {
852                SpanlessEq::eq(normal, normal2)
853            }
854            (AttrKind::DocComment(kind, symbol), AttrKind::DocComment(kind2, symbol2)) => {
855                SpanlessEq::eq(kind, kind2) && SpanlessEq::eq(symbol, symbol2)
856            }
857            (AttrKind::DocComment(kind, unescaped), AttrKind::Normal(normal2)) => {
858                match kind {
859                    CommentKind::Line | CommentKind::Block => {}
860                }
861                let path = Path::from_ident(Ident::with_dummy_span(sym::doc));
862                SpanlessEq::eq(&path, &normal2.item.path)
863                    && match &normal2.item.args {
864                        AttrArgs::Empty | AttrArgs::Delimited(_) => false,
865                        AttrArgs::Eq(_span, value) => {
866                            is_escaped_literal_attr_args(value, *unescaped)
867                        }
868                    }
869            }
870            (AttrKind::Normal(_), AttrKind::DocComment(..)) => SpanlessEq::eq(other, self),
871        }
872    }
873}
874
875impl SpanlessEq for FormatArguments {
876    fn eq(&self, other: &Self) -> bool {
877        SpanlessEq::eq(self.all_args(), other.all_args())
878    }
879}
880