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