]> git.proxmox.com Git - rustc.git/blob - vendor/syn/tests/common/eq.rs
New upstream version 1.51.0+dfsg1
[rustc.git] / vendor / syn / tests / common / eq.rs
1 extern crate rustc_ast;
2 extern crate rustc_data_structures;
3 extern crate rustc_span;
4
5 use rustc_ast::ast::{
6 AngleBracketedArg, AngleBracketedArgs, AnonConst, Arm, AssocItemKind, AssocTyConstraint,
7 AssocTyConstraintKind, Async, AttrId, AttrItem, AttrKind, AttrStyle, Attribute, BareFnTy,
8 BinOpKind, BindingMode, Block, BlockCheckMode, BorrowKind, CaptureBy, Const, Crate, CrateSugar,
9 Defaultness, EnumDef, Expr, ExprKind, Extern, Field, FieldPat, FloatTy, FnDecl, FnHeader,
10 FnRetTy, FnSig, ForeignItemKind, ForeignMod, GenericArg, GenericArgs, GenericBound,
11 GenericParam, GenericParamKind, Generics, GlobalAsm, ImplPolarity, InlineAsm, InlineAsmOperand,
12 InlineAsmOptions, InlineAsmRegOrRegClass, InlineAsmTemplatePiece, IntTy, IsAuto, Item,
13 ItemKind, Label, Lifetime, Lit, LitFloatType, LitIntType, LitKind, LlvmAsmDialect,
14 LlvmInlineAsm, LlvmInlineAsmOutput, Local, MacArgs, MacCall, MacCallStmt, MacDelimiter,
15 MacStmtStyle, MacroDef, Mod, Movability, MutTy, Mutability, NodeId, Param, ParenthesizedArgs,
16 Pat, PatKind, Path, PathSegment, PolyTraitRef, QSelf, RangeEnd, RangeLimits, RangeSyntax, Stmt,
17 StmtKind, StrLit, StrStyle, StructField, StructRest, TraitBoundModifier, TraitObjectSyntax,
18 TraitRef, Ty, TyKind, UintTy, UnOp, Unsafe, UnsafeSource, UseTree, UseTreeKind, Variant,
19 VariantData, Visibility, VisibilityKind, WhereBoundPredicate, WhereClause, WhereEqPredicate,
20 WherePredicate, WhereRegionPredicate,
21 };
22 use rustc_ast::ptr::P;
23 use rustc_ast::token::{self, CommentKind, DelimToken, Nonterminal, Token, TokenKind};
24 use rustc_ast::tokenstream::{DelimSpan, LazyTokenStream, TokenStream, TokenTree};
25 use rustc_data_structures::sync::Lrc;
26 use rustc_data_structures::thin_vec::ThinVec;
27 use rustc_span::source_map::Spanned;
28 use rustc_span::symbol::{sym, Ident};
29 use rustc_span::{Span, Symbol, SyntaxContext, DUMMY_SP};
30
31 pub trait SpanlessEq {
32 fn eq(&self, other: &Self) -> bool;
33 }
34
35 impl<T: SpanlessEq> SpanlessEq for P<T> {
36 fn eq(&self, other: &Self) -> bool {
37 SpanlessEq::eq(&**self, &**other)
38 }
39 }
40
41 impl<T: ?Sized + SpanlessEq> SpanlessEq for Lrc<T> {
42 fn eq(&self, other: &Self) -> bool {
43 SpanlessEq::eq(&**self, &**other)
44 }
45 }
46
47 impl<T: SpanlessEq> SpanlessEq for Option<T> {
48 fn eq(&self, other: &Self) -> bool {
49 match (self, other) {
50 (None, None) => true,
51 (Some(this), Some(other)) => SpanlessEq::eq(this, other),
52 _ => false,
53 }
54 }
55 }
56
57 impl<T: SpanlessEq> SpanlessEq for [T] {
58 fn eq(&self, other: &Self) -> bool {
59 self.len() == other.len() && self.iter().zip(other).all(|(a, b)| SpanlessEq::eq(a, b))
60 }
61 }
62
63 impl<T: SpanlessEq> SpanlessEq for Vec<T> {
64 fn eq(&self, other: &Self) -> bool {
65 <[T] as SpanlessEq>::eq(self, other)
66 }
67 }
68
69 impl<T: SpanlessEq> SpanlessEq for ThinVec<T> {
70 fn eq(&self, other: &Self) -> bool {
71 self.len() == other.len()
72 && self
73 .iter()
74 .zip(other.iter())
75 .all(|(a, b)| SpanlessEq::eq(a, b))
76 }
77 }
78
79 impl<T: SpanlessEq> SpanlessEq for Spanned<T> {
80 fn eq(&self, other: &Self) -> bool {
81 SpanlessEq::eq(&self.node, &other.node)
82 }
83 }
84
85 impl<A: SpanlessEq, B: SpanlessEq> SpanlessEq for (A, B) {
86 fn eq(&self, other: &Self) -> bool {
87 SpanlessEq::eq(&self.0, &other.0) && SpanlessEq::eq(&self.1, &other.1)
88 }
89 }
90
91 macro_rules! spanless_eq_true {
92 ($name:ty) => {
93 impl SpanlessEq for $name {
94 fn eq(&self, _other: &Self) -> bool {
95 true
96 }
97 }
98 };
99 }
100
101 spanless_eq_true!(Span);
102 spanless_eq_true!(DelimSpan);
103 spanless_eq_true!(AttrId);
104 spanless_eq_true!(NodeId);
105 spanless_eq_true!(SyntaxContext);
106
107 macro_rules! spanless_eq_partial_eq {
108 ($name:ty) => {
109 impl SpanlessEq for $name {
110 fn eq(&self, other: &Self) -> bool {
111 PartialEq::eq(self, other)
112 }
113 }
114 };
115 }
116
117 spanless_eq_partial_eq!(bool);
118 spanless_eq_partial_eq!(u8);
119 spanless_eq_partial_eq!(u16);
120 spanless_eq_partial_eq!(u128);
121 spanless_eq_partial_eq!(usize);
122 spanless_eq_partial_eq!(char);
123 spanless_eq_partial_eq!(String);
124 spanless_eq_partial_eq!(Symbol);
125 spanless_eq_partial_eq!(CommentKind);
126 spanless_eq_partial_eq!(DelimToken);
127 spanless_eq_partial_eq!(InlineAsmOptions);
128 spanless_eq_partial_eq!(token::LitKind);
129
130 macro_rules! spanless_eq_struct {
131 {
132 $($name:ident)::+ $(<$param:ident>)?;
133 $([$field:ident $other:ident])*
134 $(![$ignore:ident])*
135 } => {
136 impl $(<$param: SpanlessEq>)* SpanlessEq for $($name)::+ $(<$param>)* {
137 fn eq(&self, other: &Self) -> bool {
138 let $($name)::+ { $($field,)* $($ignore: _,)* } = self;
139 let $($name)::+ { $($field: $other,)* $($ignore: _,)* } = other;
140 true $(&& SpanlessEq::eq($field, $other))*
141 }
142 }
143 };
144
145 {
146 $($name:ident)::+ $(<$param:ident>)?;
147 $([$field:ident $other:ident])*
148 $(![$ignore:ident])*
149 $next:ident
150 $($rest:tt)*
151 } => {
152 spanless_eq_struct! {
153 $($name)::+ $(<$param>)*;
154 $([$field $other])*
155 [$next other]
156 $(![$ignore])*
157 $($rest)*
158 }
159 };
160
161 {
162 $($name:ident)::+ $(<$param:ident>)?;
163 $([$field:ident $other:ident])*
164 $(![$ignore:ident])*
165 !$next:ident
166 $($rest:tt)*
167 } => {
168 spanless_eq_struct! {
169 $($name)::+ $(<$param>)*;
170 $([$field $other])*
171 $(![$ignore])*
172 ![$next]
173 $($rest)*
174 }
175 };
176 }
177
178 macro_rules! spanless_eq_enum {
179 {
180 $($name:ident)::+;
181 $([$($variant:ident)::+; $([$field:tt $this:ident $other:ident])* $(![$ignore:tt])*])*
182 } => {
183 impl SpanlessEq for $($name)::+ {
184 fn eq(&self, other: &Self) -> bool {
185 match self {
186 $(
187 $($variant)::+ { .. } => {}
188 )*
189 }
190 #[allow(unreachable_patterns)]
191 match (self, other) {
192 $(
193 (
194 $($variant)::+ { $($field: $this,)* $($ignore: _,)* },
195 $($variant)::+ { $($field: $other,)* $($ignore: _,)* },
196 ) => {
197 true $(&& SpanlessEq::eq($this, $other))*
198 }
199 )*
200 _ => false,
201 }
202 }
203 }
204 };
205
206 {
207 $($name:ident)::+;
208 $([$($variant:ident)::+; $($fields:tt)*])*
209 $next:ident [$([$($named:tt)*])* $(![$ignore:tt])*] (!$i:tt $($field:tt)*)
210 $($rest:tt)*
211 } => {
212 spanless_eq_enum! {
213 $($name)::+;
214 $([$($variant)::+; $($fields)*])*
215 $next [$([$($named)*])* $(![$ignore])* ![$i]] ($($field)*)
216 $($rest)*
217 }
218 };
219
220 {
221 $($name:ident)::+;
222 $([$($variant:ident)::+; $($fields:tt)*])*
223 $next:ident [$([$($named:tt)*])* $(![$ignore:tt])*] ($i:tt $($field:tt)*)
224 $($rest:tt)*
225 } => {
226 spanless_eq_enum! {
227 $($name)::+;
228 $([$($variant)::+; $($fields)*])*
229 $next [$([$($named)*])* [$i this other] $(![$ignore])*] ($($field)*)
230 $($rest)*
231 }
232 };
233
234 {
235 $($name:ident)::+;
236 $([$($variant:ident)::+; $($fields:tt)*])*
237 $next:ident [$($named:tt)*] ()
238 $($rest:tt)*
239 } => {
240 spanless_eq_enum! {
241 $($name)::+;
242 $([$($variant)::+; $($fields)*])*
243 [$($name)::+::$next; $($named)*]
244 $($rest)*
245 }
246 };
247
248 {
249 $($name:ident)::+;
250 $([$($variant:ident)::+; $($fields:tt)*])*
251 $next:ident ($($field:tt)*)
252 $($rest:tt)*
253 } => {
254 spanless_eq_enum! {
255 $($name)::+;
256 $([$($variant)::+; $($fields)*])*
257 $next [] ($($field)*)
258 $($rest)*
259 }
260 };
261
262 {
263 $($name:ident)::+;
264 $([$($variant:ident)::+; $($fields:tt)*])*
265 $next:ident
266 $($rest:tt)*
267 } => {
268 spanless_eq_enum! {
269 $($name)::+;
270 $([$($variant)::+; $($fields)*])*
271 [$($name)::+::$next;]
272 $($rest)*
273 }
274 };
275 }
276
277 spanless_eq_struct!(AngleBracketedArgs; span args);
278 spanless_eq_struct!(AnonConst; id value);
279 spanless_eq_struct!(Arm; attrs pat guard body span id is_placeholder);
280 spanless_eq_struct!(AssocTyConstraint; id ident gen_args kind span);
281 spanless_eq_struct!(AttrItem; path args tokens);
282 spanless_eq_struct!(Attribute; kind id style span);
283 spanless_eq_struct!(BareFnTy; unsafety ext generic_params decl);
284 spanless_eq_struct!(Block; stmts id rules span tokens);
285 spanless_eq_struct!(Crate; module attrs span proc_macros);
286 spanless_eq_struct!(EnumDef; variants);
287 spanless_eq_struct!(Expr; id kind span attrs !tokens);
288 spanless_eq_struct!(Field; attrs id span ident expr is_shorthand is_placeholder);
289 spanless_eq_struct!(FieldPat; ident pat is_shorthand attrs id span is_placeholder);
290 spanless_eq_struct!(FnDecl; inputs output);
291 spanless_eq_struct!(FnHeader; constness asyncness unsafety ext);
292 spanless_eq_struct!(FnSig; header decl span);
293 spanless_eq_struct!(ForeignMod; unsafety abi items);
294 spanless_eq_struct!(GenericParam; id ident attrs bounds is_placeholder kind);
295 spanless_eq_struct!(Generics; params where_clause span);
296 spanless_eq_struct!(GlobalAsm; asm);
297 spanless_eq_struct!(InlineAsm; template operands options line_spans);
298 spanless_eq_struct!(Item<K>; attrs id span vis ident kind !tokens);
299 spanless_eq_struct!(Label; ident);
300 spanless_eq_struct!(Lifetime; id ident);
301 spanless_eq_struct!(Lit; token kind span);
302 spanless_eq_struct!(LlvmInlineAsm; asm asm_str_style outputs inputs clobbers volatile alignstack dialect);
303 spanless_eq_struct!(LlvmInlineAsmOutput; constraint expr is_rw is_indirect);
304 spanless_eq_struct!(Local; pat ty init id span attrs !tokens);
305 spanless_eq_struct!(MacCall; path args prior_type_ascription);
306 spanless_eq_struct!(MacCallStmt; mac style attrs tokens);
307 spanless_eq_struct!(MacroDef; body macro_rules);
308 spanless_eq_struct!(Mod; inner unsafety items inline);
309 spanless_eq_struct!(MutTy; ty mutbl);
310 spanless_eq_struct!(ParenthesizedArgs; span inputs inputs_span output);
311 spanless_eq_struct!(Pat; id kind span tokens);
312 spanless_eq_struct!(Path; span segments tokens);
313 spanless_eq_struct!(PathSegment; ident id args);
314 spanless_eq_struct!(PolyTraitRef; bound_generic_params trait_ref span);
315 spanless_eq_struct!(QSelf; ty path_span position);
316 spanless_eq_struct!(Stmt; id kind span);
317 spanless_eq_struct!(StrLit; style symbol suffix span symbol_unescaped);
318 spanless_eq_struct!(StructField; attrs id span vis ident ty is_placeholder);
319 spanless_eq_struct!(Token; kind span);
320 spanless_eq_struct!(TraitRef; path ref_id);
321 spanless_eq_struct!(Ty; id kind span tokens);
322 spanless_eq_struct!(UseTree; prefix kind span);
323 spanless_eq_struct!(Variant; attrs id span !vis ident data disr_expr is_placeholder);
324 spanless_eq_struct!(Visibility; kind span tokens);
325 spanless_eq_struct!(WhereBoundPredicate; span bound_generic_params bounded_ty bounds);
326 spanless_eq_struct!(WhereClause; has_where_token predicates span);
327 spanless_eq_struct!(WhereEqPredicate; id span lhs_ty rhs_ty);
328 spanless_eq_struct!(WhereRegionPredicate; span lifetime bounds);
329 spanless_eq_struct!(token::Lit; kind symbol suffix);
330 spanless_eq_enum!(AngleBracketedArg; Arg(0) Constraint(0));
331 spanless_eq_enum!(AssocItemKind; Const(0 1 2) Fn(0 1 2 3) TyAlias(0 1 2 3) MacCall(0));
332 spanless_eq_enum!(AssocTyConstraintKind; Equality(ty) Bound(bounds));
333 spanless_eq_enum!(Async; Yes(span closure_id return_impl_trait_id) No);
334 spanless_eq_enum!(AttrStyle; Outer Inner);
335 spanless_eq_enum!(BinOpKind; Add Sub Mul Div Rem And Or BitXor BitAnd BitOr Shl Shr Eq Lt Le Ne Ge Gt);
336 spanless_eq_enum!(BindingMode; ByRef(0) ByValue(0));
337 spanless_eq_enum!(BlockCheckMode; Default Unsafe(0));
338 spanless_eq_enum!(BorrowKind; Ref Raw);
339 spanless_eq_enum!(CaptureBy; Value Ref);
340 spanless_eq_enum!(Const; Yes(0) No);
341 spanless_eq_enum!(CrateSugar; PubCrate JustCrate);
342 spanless_eq_enum!(Defaultness; Default(0) Final);
343 spanless_eq_enum!(Extern; None Implicit Explicit(0));
344 spanless_eq_enum!(FloatTy; F32 F64);
345 spanless_eq_enum!(FnRetTy; Default(0) Ty(0));
346 spanless_eq_enum!(ForeignItemKind; Static(0 1 2) Fn(0 1 2 3) TyAlias(0 1 2 3) MacCall(0));
347 spanless_eq_enum!(GenericArg; Lifetime(0) Type(0) Const(0));
348 spanless_eq_enum!(GenericArgs; AngleBracketed(0) Parenthesized(0));
349 spanless_eq_enum!(GenericBound; Trait(0 1) Outlives(0));
350 spanless_eq_enum!(GenericParamKind; Lifetime Type(default) Const(ty kw_span default));
351 spanless_eq_enum!(ImplPolarity; Positive Negative(0));
352 spanless_eq_enum!(InlineAsmRegOrRegClass; Reg(0) RegClass(0));
353 spanless_eq_enum!(InlineAsmTemplatePiece; String(0) Placeholder(operand_idx modifier span));
354 spanless_eq_enum!(IntTy; Isize I8 I16 I32 I64 I128);
355 spanless_eq_enum!(IsAuto; Yes No);
356 spanless_eq_enum!(LitFloatType; Suffixed(0) Unsuffixed);
357 spanless_eq_enum!(LitIntType; Signed(0) Unsigned(0) Unsuffixed);
358 spanless_eq_enum!(LlvmAsmDialect; Att Intel);
359 spanless_eq_enum!(MacArgs; Empty Delimited(0 1 2) Eq(0 1));
360 spanless_eq_enum!(MacDelimiter; Parenthesis Bracket Brace);
361 spanless_eq_enum!(MacStmtStyle; Semicolon Braces NoBraces);
362 spanless_eq_enum!(Movability; Static Movable);
363 spanless_eq_enum!(Mutability; Mut Not);
364 spanless_eq_enum!(RangeEnd; Included(0) Excluded);
365 spanless_eq_enum!(RangeLimits; HalfOpen Closed);
366 spanless_eq_enum!(StmtKind; Local(0) Item(0) Expr(0) Semi(0) Empty MacCall(0));
367 spanless_eq_enum!(StrStyle; Cooked Raw(0));
368 spanless_eq_enum!(StructRest; Base(0) Rest(0) None);
369 spanless_eq_enum!(TokenTree; Token(0) Delimited(0 1 2));
370 spanless_eq_enum!(TraitBoundModifier; None Maybe MaybeConst MaybeConstMaybe);
371 spanless_eq_enum!(TraitObjectSyntax; Dyn None);
372 spanless_eq_enum!(UintTy; Usize U8 U16 U32 U64 U128);
373 spanless_eq_enum!(UnOp; Deref Not Neg);
374 spanless_eq_enum!(Unsafe; Yes(0) No);
375 spanless_eq_enum!(UnsafeSource; CompilerGenerated UserProvided);
376 spanless_eq_enum!(UseTreeKind; Simple(0 1 2) Nested(0) Glob);
377 spanless_eq_enum!(VariantData; Struct(0 1) Tuple(0 1) Unit(0));
378 spanless_eq_enum!(VisibilityKind; Public Crate(0) Restricted(path id) Inherited);
379 spanless_eq_enum!(WherePredicate; BoundPredicate(0) RegionPredicate(0) EqPredicate(0));
380 spanless_eq_enum!(ExprKind; Box(0) Array(0) ConstBlock(0) Call(0 1)
381 MethodCall(0 1 2) Tup(0) Binary(0 1 2) Unary(0 1) Lit(0) Cast(0 1) Type(0 1)
382 Let(0 1) If(0 1 2) While(0 1 2) ForLoop(0 1 2 3) Loop(0 1) Match(0 1)
383 Closure(0 1 2 3 4 5) Block(0 1) Async(0 1 2) Await(0) TryBlock(0)
384 Assign(0 1 2) AssignOp(0 1 2) Field(0 1) Index(0 1) Underscore Range(0 1 2)
385 Path(0 1) AddrOf(0 1 2) Break(0 1) Continue(0) Ret(0) InlineAsm(0)
386 LlvmInlineAsm(0) MacCall(0) Struct(0 1 2) Repeat(0 1) Paren(0) Try(0)
387 Yield(0) Err);
388 spanless_eq_enum!(InlineAsmOperand; In(reg expr) Out(reg late expr)
389 InOut(reg late expr) SplitInOut(reg late in_expr out_expr) Const(expr)
390 Sym(expr));
391 spanless_eq_enum!(ItemKind; ExternCrate(0) Use(0) Static(0 1 2) Const(0 1 2)
392 Fn(0 1 2 3) Mod(0) ForeignMod(0) GlobalAsm(0) TyAlias(0 1 2 3) Enum(0 1)
393 Struct(0 1) Union(0 1) Trait(0 1 2 3 4) TraitAlias(0 1)
394 Impl(unsafety polarity defaultness constness generics of_trait self_ty items)
395 MacCall(0) MacroDef(0));
396 spanless_eq_enum!(LitKind; Str(0 1) ByteStr(0) Byte(0) Char(0) Int(0 1)
397 Float(0 1) Bool(0) Err(0));
398 spanless_eq_enum!(PatKind; Wild Ident(0 1 2) Struct(0 1 2) TupleStruct(0 1)
399 Or(0) Path(0 1) Tuple(0) Box(0) Ref(0 1) Lit(0) Range(0 1 2) Slice(0) Rest
400 Paren(0) MacCall(0));
401 spanless_eq_enum!(TyKind; Slice(0) Array(0 1) Ptr(0) Rptr(0 1) BareFn(0) Never
402 Tup(0) Path(0 1) TraitObject(0 1) ImplTrait(0 1) Paren(0) Typeof(0) Infer
403 ImplicitSelf MacCall(0) Err CVarArgs);
404
405 impl SpanlessEq for Ident {
406 fn eq(&self, other: &Self) -> bool {
407 self.as_str() == other.as_str()
408 }
409 }
410
411 impl SpanlessEq for RangeSyntax {
412 fn eq(&self, _other: &Self) -> bool {
413 match self {
414 RangeSyntax::DotDotDot | RangeSyntax::DotDotEq => true,
415 }
416 }
417 }
418
419 impl SpanlessEq for Param {
420 fn eq(&self, other: &Self) -> bool {
421 let Param {
422 attrs,
423 ty,
424 pat,
425 id,
426 span: _,
427 is_placeholder,
428 } = self;
429 let Param {
430 attrs: attrs2,
431 ty: ty2,
432 pat: pat2,
433 id: id2,
434 span: _,
435 is_placeholder: is_placeholder2,
436 } = other;
437 SpanlessEq::eq(id, id2)
438 && SpanlessEq::eq(is_placeholder, is_placeholder2)
439 && (matches!(ty.kind, TyKind::Err)
440 || matches!(ty2.kind, TyKind::Err)
441 || SpanlessEq::eq(attrs, attrs2)
442 && SpanlessEq::eq(ty, ty2)
443 && SpanlessEq::eq(pat, pat2))
444 }
445 }
446
447 impl SpanlessEq for TokenKind {
448 fn eq(&self, other: &Self) -> bool {
449 match (self, other) {
450 (TokenKind::Literal(this), TokenKind::Literal(other)) => SpanlessEq::eq(this, other),
451 (TokenKind::DotDotEq, _) | (TokenKind::DotDotDot, _) => match other {
452 TokenKind::DotDotEq | TokenKind::DotDotDot => true,
453 _ => false,
454 },
455 (TokenKind::Interpolated(this), TokenKind::Interpolated(other)) => {
456 match (this.as_ref(), other.as_ref()) {
457 (Nonterminal::NtExpr(this), Nonterminal::NtExpr(other)) => {
458 SpanlessEq::eq(this, other)
459 }
460 _ => this == other,
461 }
462 }
463 _ => self == other,
464 }
465 }
466 }
467
468 impl SpanlessEq for TokenStream {
469 fn eq(&self, other: &Self) -> bool {
470 let mut this_trees = self.trees_ref();
471 let mut other_trees = other.trees_ref();
472 loop {
473 let this = match this_trees.next() {
474 None => return other_trees.next().is_none(),
475 Some(tree) => tree,
476 };
477 let other = match other_trees.next() {
478 None => return false,
479 Some(tree) => tree,
480 };
481 if SpanlessEq::eq(this, other) {
482 continue;
483 }
484 if let (TokenTree::Token(this), TokenTree::Token(other)) = (this, other) {
485 if match (&this.kind, &other.kind) {
486 (TokenKind::Literal(this), TokenKind::Literal(other)) => {
487 SpanlessEq::eq(this, other)
488 }
489 (TokenKind::DocComment(_kind, style, symbol), TokenKind::Pound) => {
490 doc_comment(*style, *symbol, &mut other_trees)
491 }
492 (TokenKind::Pound, TokenKind::DocComment(_kind, style, symbol)) => {
493 doc_comment(*style, *symbol, &mut this_trees)
494 }
495 _ => false,
496 } {
497 continue;
498 }
499 }
500 return false;
501 }
502 }
503 }
504
505 fn doc_comment<'a>(
506 style: AttrStyle,
507 unescaped: Symbol,
508 trees: &mut impl Iterator<Item = &'a TokenTree>,
509 ) -> bool {
510 if match style {
511 AttrStyle::Outer => false,
512 AttrStyle::Inner => true,
513 } {
514 match trees.next() {
515 Some(TokenTree::Token(Token {
516 kind: TokenKind::Not,
517 span: _,
518 })) => {}
519 _ => return false,
520 }
521 }
522 let stream = match trees.next() {
523 Some(TokenTree::Delimited(_span, DelimToken::Bracket, stream)) => stream,
524 _ => return false,
525 };
526 let mut trees = stream.trees_ref();
527 match trees.next() {
528 Some(TokenTree::Token(Token {
529 kind: TokenKind::Ident(symbol, false),
530 span: _,
531 })) if *symbol == sym::doc => {}
532 _ => return false,
533 }
534 match trees.next() {
535 Some(TokenTree::Token(Token {
536 kind: TokenKind::Eq,
537 span: _,
538 })) => {}
539 _ => return false,
540 }
541 match trees.next() {
542 Some(TokenTree::Token(token)) => {
543 is_escaped_literal(token, unescaped) && trees.next().is_none()
544 }
545 _ => false,
546 }
547 }
548
549 fn is_escaped_literal(token: &Token, unescaped: Symbol) -> bool {
550 match match token {
551 Token {
552 kind: TokenKind::Literal(lit),
553 span: _,
554 } => Lit::from_lit_token(*lit, DUMMY_SP),
555 Token {
556 kind: TokenKind::Interpolated(nonterminal),
557 span: _,
558 } => match nonterminal.as_ref() {
559 Nonterminal::NtExpr(expr) => match &expr.kind {
560 ExprKind::Lit(lit) => Ok(lit.clone()),
561 _ => return false,
562 },
563 _ => return false,
564 },
565 _ => return false,
566 } {
567 Ok(Lit {
568 token:
569 token::Lit {
570 kind: token::LitKind::Str,
571 symbol: _,
572 suffix: None,
573 },
574 kind: LitKind::Str(symbol, StrStyle::Cooked),
575 span: _,
576 }) => symbol.as_str().replace('\r', "") == unescaped.as_str().replace('\r', ""),
577 _ => false,
578 }
579 }
580
581 impl SpanlessEq for LazyTokenStream {
582 fn eq(&self, other: &Self) -> bool {
583 let this = self.create_token_stream();
584 let other = other.create_token_stream();
585 SpanlessEq::eq(&this, &other)
586 }
587 }
588
589 impl SpanlessEq for AttrKind {
590 fn eq(&self, other: &Self) -> bool {
591 match (self, other) {
592 (AttrKind::Normal(item, tokens), AttrKind::Normal(item2, tokens2)) => {
593 SpanlessEq::eq(item, item2) && SpanlessEq::eq(tokens, tokens2)
594 }
595 (AttrKind::DocComment(kind, symbol), AttrKind::DocComment(kind2, symbol2)) => {
596 SpanlessEq::eq(kind, kind2) && SpanlessEq::eq(symbol, symbol2)
597 }
598 (AttrKind::DocComment(kind, unescaped), AttrKind::Normal(item2, _tokens)) => {
599 match kind {
600 CommentKind::Line | CommentKind::Block => {}
601 }
602 let path = Path::from_ident(Ident::with_dummy_span(sym::doc));
603 SpanlessEq::eq(&path, &item2.path)
604 && match &item2.args {
605 MacArgs::Empty | MacArgs::Delimited(..) => false,
606 MacArgs::Eq(_span, token) => is_escaped_literal(token, *unescaped),
607 }
608 }
609 (AttrKind::Normal(..), AttrKind::DocComment(..)) => SpanlessEq::eq(other, self),
610 }
611 }
612 }