blob: 4353532eecd0fffa5463c7d741a4bd9a6cd92cb6 [file] [log] [blame]
David Tolnayecd024d2018-07-21 09:07:56 -07001extern crate rustc_data_structures;
2extern crate rustc_target;
3extern crate syntax;
4extern crate syntax_pos;
5
6use std::mem;
7
8use self::rustc_data_structures::sync::Lrc;
David Tolnayc8659922018-08-14 22:40:50 -07009use self::rustc_data_structures::thin_vec::ThinVec;
David Tolnayecd024d2018-07-21 09:07:56 -070010use self::rustc_target::abi::FloatTy;
11use self::rustc_target::spec::abi::Abi;
12use self::syntax::ast::{
David Tolnayae019182019-04-24 03:16:48 -070013 AngleBracketedArgs, AnonConst, Arg, ArgSource, Arm, AsmDialect, AsyncArgument, AttrId,
David Tolnay0db515d2019-05-08 17:58:12 -070014 AttrStyle, Attribute, AwaitOrigin, BareFnTy, BinOpKind, BindingMode, Block, BlockCheckMode,
15 CaptureBy, Constness, Crate, CrateSugar, Defaultness, EnumDef, Expr, ExprKind, Field, FieldPat,
16 FnDecl, FnHeader, ForeignItem, ForeignItemKind, ForeignMod, FunctionRetTy, GenericArg,
17 GenericArgs, GenericBound, GenericParam, GenericParamKind, Generics, GlobalAsm, Guard, Ident,
18 ImplItem, ImplItemKind, ImplPolarity, InlineAsm, InlineAsmOutput, IntTy, IsAsync, IsAuto, Item,
David Tolnay2979f982019-05-13 21:04:38 -070019 ItemKind, Label, Lifetime, Lit, LitIntType, LitKind, Local, LocalSource, MacDelimiter,
20 MacStmtStyle, Mac_, MacroDef, MethodSig, Mod, Movability, MutTy, Mutability, NodeId,
21 ParenthesizedArgs, Pat, PatKind, Path, PathSegment, PolyTraitRef, QSelf, RangeEnd, RangeLimits,
22 RangeSyntax, Stmt, StmtKind, StrStyle, StructField, TraitBoundModifier, TraitItem,
23 TraitItemKind, TraitObjectSyntax, TraitRef, Ty, TyKind, TypeBinding, UintTy, UnOp,
24 UnsafeSource, Unsafety, UseTree, UseTreeKind, VariantData, Variant_, VisibilityKind,
25 WhereBoundPredicate, WhereClause, WhereEqPredicate, WherePredicate, WhereRegionPredicate,
David Tolnayecd024d2018-07-21 09:07:56 -070026};
David Tolnayecd024d2018-07-21 09:07:56 -070027use self::syntax::parse::lexer::comments;
David Tolnay2979f982019-05-13 21:04:38 -070028use self::syntax::parse::token::{self, DelimToken, Token};
David Tolnayecd024d2018-07-21 09:07:56 -070029use self::syntax::ptr::P;
David Tolnayd1c31cc2018-08-24 14:47:15 -040030use self::syntax::source_map::Spanned;
David Tolnayecd024d2018-07-21 09:07:56 -070031use self::syntax::symbol::Symbol;
David Tolnay29bfbf32019-01-19 20:59:37 -080032use self::syntax::tokenstream::{DelimSpan, TokenStream, TokenTree};
David Tolnayecd024d2018-07-21 09:07:56 -070033use self::syntax_pos::{Span, SyntaxContext, DUMMY_SP};
34
35pub trait SpanlessEq {
36 fn eq(&self, other: &Self) -> bool;
37}
38
39impl<T: SpanlessEq> SpanlessEq for P<T> {
40 fn eq(&self, other: &Self) -> bool {
41 SpanlessEq::eq(&**self, &**other)
42 }
43}
44
45impl<T: SpanlessEq> SpanlessEq for Lrc<T> {
46 fn eq(&self, other: &Self) -> bool {
47 SpanlessEq::eq(&**self, &**other)
48 }
49}
50
51impl<T: SpanlessEq> SpanlessEq for Option<T> {
52 fn eq(&self, other: &Self) -> bool {
53 match (self, other) {
54 (None, None) => true,
55 (Some(this), Some(other)) => SpanlessEq::eq(this, other),
56 _ => false,
57 }
58 }
59}
60
61impl<T: SpanlessEq> SpanlessEq for Vec<T> {
62 fn eq(&self, other: &Self) -> bool {
63 self.len() == other.len() && self.iter().zip(other).all(|(a, b)| SpanlessEq::eq(a, b))
64 }
65}
66
67impl<T: SpanlessEq> SpanlessEq for ThinVec<T> {
68 fn eq(&self, other: &Self) -> bool {
David Tolnaye614f282018-10-27 22:50:12 -070069 self.len() == other.len()
70 && self
71 .iter()
72 .zip(other.iter())
73 .all(|(a, b)| SpanlessEq::eq(a, b))
David Tolnayecd024d2018-07-21 09:07:56 -070074 }
75}
76
77impl<T: SpanlessEq> SpanlessEq for Spanned<T> {
78 fn eq(&self, other: &Self) -> bool {
79 SpanlessEq::eq(&self.node, &other.node)
80 }
81}
82
83impl<A: SpanlessEq, B: SpanlessEq> SpanlessEq for (A, B) {
84 fn eq(&self, other: &Self) -> bool {
85 SpanlessEq::eq(&self.0, &other.0) && SpanlessEq::eq(&self.1, &other.1)
86 }
87}
88
89impl<A: SpanlessEq, B: SpanlessEq, C: SpanlessEq> SpanlessEq for (A, B, C) {
90 fn eq(&self, other: &Self) -> bool {
91 SpanlessEq::eq(&self.0, &other.0)
92 && SpanlessEq::eq(&self.1, &other.1)
93 && SpanlessEq::eq(&self.2, &other.2)
94 }
95}
96
97macro_rules! spanless_eq_true {
98 ($name:ident) => {
99 impl SpanlessEq for $name {
100 fn eq(&self, _other: &Self) -> bool {
101 true
102 }
103 }
104 };
105}
106
107spanless_eq_true!(Span);
David Tolnay2b940f62018-09-09 22:16:07 -0700108spanless_eq_true!(DelimSpan);
David Tolnayecd024d2018-07-21 09:07:56 -0700109spanless_eq_true!(AttrId);
110spanless_eq_true!(NodeId);
111spanless_eq_true!(SyntaxContext);
112
113macro_rules! spanless_eq_partial_eq {
114 ($name:ident) => {
115 impl SpanlessEq for $name {
116 fn eq(&self, other: &Self) -> bool {
117 PartialEq::eq(self, other)
118 }
119 }
120 };
121}
122
123spanless_eq_partial_eq!(bool);
124spanless_eq_partial_eq!(u8);
125spanless_eq_partial_eq!(u16);
126spanless_eq_partial_eq!(u128);
127spanless_eq_partial_eq!(usize);
128spanless_eq_partial_eq!(char);
129spanless_eq_partial_eq!(Symbol);
130spanless_eq_partial_eq!(Abi);
131spanless_eq_partial_eq!(DelimToken);
132
133macro_rules! spanless_eq_struct {
134 {
135 $name:ident;
136 $([$field:ident $other:ident])*
137 $(![$ignore:ident])*
138 } => {
139 impl SpanlessEq for $name {
140 fn eq(&self, other: &Self) -> bool {
141 let $name { $($field,)* $($ignore: _,)* } = self;
142 let $name { $($field: $other,)* $($ignore: _,)* } = other;
143 $(SpanlessEq::eq($field, $other))&&*
144 }
145 }
146 };
147
148 {
149 $name:ident;
150 $([$field:ident $other:ident])*
151 $next:ident
152 $($rest:ident)*
153 $(!$ignore:ident)*
154 } => {
155 spanless_eq_struct! {
156 $name;
157 $([$field $other])*
158 [$next other]
159 $($rest)*
160 $(!$ignore)*
161 }
162 };
163
164 {
165 $name:ident;
166 $([$field:ident $other:ident])*
167 $(![$ignore:ident])*
168 !$next:ident
169 $(!$rest:ident)*
170 } => {
171 spanless_eq_struct! {
172 $name;
173 $([$field $other])*
174 $(![$ignore])*
175 ![$next]
176 $(!$rest)*
177 }
178 };
179}
180
181macro_rules! spanless_eq_enum {
182 {
183 $name:ident;
184 $([$variant:ident $([$field:tt $this:ident $other:ident])*])*
185 } => {
186 impl SpanlessEq for $name {
187 fn eq(&self, other: &Self) -> bool {
188 match self {
189 $(
190 $name::$variant { .. } => {}
191 )*
192 }
David Tolnay83c89012018-09-01 18:15:53 -0700193 #[allow(unreachable_patterns)]
David Tolnayecd024d2018-07-21 09:07:56 -0700194 match (self, other) {
195 $(
196 (
197 $name::$variant { $($field: $this),* },
198 $name::$variant { $($field: $other),* },
199 ) => {
200 true $(&& SpanlessEq::eq($this, $other))*
201 }
202 )*
203 _ => false,
204 }
205 }
206 }
207 };
208
209 {
210 $name:ident;
211 $([$variant:ident $($fields:tt)*])*
212 $next:ident [$($named:tt)*] ( $i:tt $($field:tt)* )
213 $($rest:tt)*
214 } => {
215 spanless_eq_enum! {
216 $name;
217 $([$variant $($fields)*])*
218 $next [$($named)* [$i this other]] ( $($field)* )
219 $($rest)*
220 }
221 };
222
223 {
224 $name:ident;
225 $([$variant:ident $($fields:tt)*])*
226 $next:ident [$($named:tt)*] ()
227 $($rest:tt)*
228 } => {
229 spanless_eq_enum! {
230 $name;
231 $([$variant $($fields)*])*
232 [$next $($named)*]
233 $($rest)*
234 }
235 };
236
237 {
238 $name:ident;
239 $([$variant:ident $($fields:tt)*])*
240 $next:ident ( $($field:tt)* )
241 $($rest:tt)*
242 } => {
243 spanless_eq_enum! {
244 $name;
245 $([$variant $($fields)*])*
246 $next [] ( $($field)* )
247 $($rest)*
248 }
249 };
250
251 {
252 $name:ident;
253 $([$variant:ident $($fields:tt)*])*
254 $next:ident
255 $($rest:tt)*
256 } => {
257 spanless_eq_enum! {
258 $name;
259 $([$variant $($fields)*])*
260 [$next]
261 $($rest)*
262 }
263 };
264}
265
266spanless_eq_struct!(AngleBracketedArgs; span args bindings);
267spanless_eq_struct!(AnonConst; id value);
David Tolnayae019182019-04-24 03:16:48 -0700268spanless_eq_struct!(Arg; ty pat id source);
David Tolnayecd024d2018-07-21 09:07:56 -0700269spanless_eq_struct!(Arm; attrs pats guard body);
David Tolnayb25e1132019-05-02 22:49:12 -0700270spanless_eq_struct!(AsyncArgument; ident arg move_stmt pat_stmt);
David Tolnayecd024d2018-07-21 09:07:56 -0700271spanless_eq_struct!(Attribute; id style path tokens span !is_sugared_doc);
272spanless_eq_struct!(BareFnTy; unsafety abi generic_params decl);
David Tolnay5f5d76a2018-12-29 00:20:35 -0500273spanless_eq_struct!(Block; stmts id rules span);
David Tolnayecd024d2018-07-21 09:07:56 -0700274spanless_eq_struct!(Crate; module attrs span);
David Tolnayecd024d2018-07-21 09:07:56 -0700275spanless_eq_struct!(EnumDef; variants);
276spanless_eq_struct!(Expr; id node span attrs);
277spanless_eq_struct!(Field; ident expr span is_shorthand attrs);
278spanless_eq_struct!(FieldPat; ident pat is_shorthand attrs);
Dan Robertsonb7aa8072019-02-08 18:38:27 +0000279spanless_eq_struct!(FnDecl; inputs output c_variadic);
David Tolnayecd024d2018-07-21 09:07:56 -0700280spanless_eq_struct!(FnHeader; unsafety asyncness constness abi);
281spanless_eq_struct!(ForeignItem; ident attrs node id span vis);
282spanless_eq_struct!(ForeignMod; abi items);
283spanless_eq_struct!(GenericParam; id ident attrs bounds kind);
284spanless_eq_struct!(Generics; params where_clause span);
285spanless_eq_struct!(GlobalAsm; asm ctxt);
286spanless_eq_struct!(ImplItem; id ident vis defaultness attrs generics node span !tokens);
287spanless_eq_struct!(InlineAsm; asm asm_str_style outputs inputs clobbers volatile alignstack dialect ctxt);
288spanless_eq_struct!(InlineAsmOutput; constraint expr is_rw is_indirect);
289spanless_eq_struct!(Item; ident attrs id node vis span !tokens);
290spanless_eq_struct!(Label; ident);
291spanless_eq_struct!(Lifetime; id ident);
David Tolnay2979f982019-05-13 21:04:38 -0700292spanless_eq_struct!(Lit; token suffix node span);
David Tolnayae019182019-04-24 03:16:48 -0700293spanless_eq_struct!(Local; pat ty init id span attrs source);
David Tolnayecd024d2018-07-21 09:07:56 -0700294spanless_eq_struct!(Mac_; path delim tts);
295spanless_eq_struct!(MacroDef; tokens legacy);
296spanless_eq_struct!(MethodSig; header decl);
David Tolnay35cb3402018-09-27 22:38:19 -0700297spanless_eq_struct!(Mod; inner items inline);
David Tolnayecd024d2018-07-21 09:07:56 -0700298spanless_eq_struct!(MutTy; ty mutbl);
David Tolnayd54cc9b2019-01-22 21:53:44 -0800299spanless_eq_struct!(ParenthesizedArgs; span inputs output);
David Tolnayecd024d2018-07-21 09:07:56 -0700300spanless_eq_struct!(Pat; id node span);
301spanless_eq_struct!(Path; span segments);
David Tolnay41280d82018-10-27 21:22:02 -0700302spanless_eq_struct!(PathSegment; ident id args);
David Tolnayecd024d2018-07-21 09:07:56 -0700303spanless_eq_struct!(PolyTraitRef; bound_generic_params trait_ref span);
304spanless_eq_struct!(QSelf; ty path_span position);
305spanless_eq_struct!(Stmt; id node span);
306spanless_eq_struct!(StructField; span ident vis id ty attrs);
307spanless_eq_struct!(TraitItem; id ident attrs generics node span !tokens);
308spanless_eq_struct!(TraitRef; path ref_id);
309spanless_eq_struct!(Ty; id node span);
310spanless_eq_struct!(TypeBinding; id ident ty span);
311spanless_eq_struct!(UseTree; prefix kind span);
David Tolnay162a5042019-03-26 08:57:26 -0300312spanless_eq_struct!(Variant_; ident attrs id data disr_expr);
David Tolnayecd024d2018-07-21 09:07:56 -0700313spanless_eq_struct!(WhereBoundPredicate; span bound_generic_params bounded_ty bounds);
314spanless_eq_struct!(WhereClause; id predicates span);
315spanless_eq_struct!(WhereEqPredicate; id span lhs_ty rhs_ty);
316spanless_eq_struct!(WhereRegionPredicate; span lifetime bounds);
David Tolnayae019182019-04-24 03:16:48 -0700317spanless_eq_enum!(ArgSource; Normal AsyncFn(0));
David Tolnayecd024d2018-07-21 09:07:56 -0700318spanless_eq_enum!(AsmDialect; Att Intel);
319spanless_eq_enum!(AttrStyle; Outer Inner);
David Tolnay0db515d2019-05-08 17:58:12 -0700320spanless_eq_enum!(AwaitOrigin; FieldLike MacroLike);
David Tolnayecd024d2018-07-21 09:07:56 -0700321spanless_eq_enum!(BinOpKind; Add Sub Mul Div Rem And Or BitXor BitAnd BitOr Shl Shr Eq Lt Le Ne Ge Gt);
322spanless_eq_enum!(BindingMode; ByRef(0) ByValue(0));
323spanless_eq_enum!(BlockCheckMode; Default Unsafe(0));
324spanless_eq_enum!(CaptureBy; Value Ref);
325spanless_eq_enum!(Constness; Const NotConst);
326spanless_eq_enum!(CrateSugar; PubCrate JustCrate);
327spanless_eq_enum!(Defaultness; Default Final);
328spanless_eq_enum!(FloatTy; F32 F64);
329spanless_eq_enum!(ForeignItemKind; Fn(0 1) Static(0 1) Ty Macro(0));
330spanless_eq_enum!(FunctionRetTy; Default(0) Ty(0));
David Tolnay9f788452019-02-09 16:00:37 +0100331spanless_eq_enum!(GenericArg; Lifetime(0) Type(0) Const(0));
David Tolnayecd024d2018-07-21 09:07:56 -0700332spanless_eq_enum!(GenericArgs; AngleBracketed(0) Parenthesized(0));
333spanless_eq_enum!(GenericBound; Trait(0 1) Outlives(0));
David Tolnay9f788452019-02-09 16:00:37 +0100334spanless_eq_enum!(GenericParamKind; Lifetime Type(default) Const(ty));
David Tolnay83c89012018-09-01 18:15:53 -0700335spanless_eq_enum!(Guard; If(0));
David Tolnay72972e72018-07-21 18:35:24 -0700336spanless_eq_enum!(ImplItemKind; Const(0 1) Method(0 1) Type(0) Existential(0) Macro(0));
David Tolnayecd024d2018-07-21 09:07:56 -0700337spanless_eq_enum!(ImplPolarity; Positive Negative);
338spanless_eq_enum!(IntTy; Isize I8 I16 I32 I64 I128);
David Tolnayae019182019-04-24 03:16:48 -0700339spanless_eq_enum!(IsAsync; Async(closure_id return_impl_trait_id arguments) NotAsync);
David Tolnayecd024d2018-07-21 09:07:56 -0700340spanless_eq_enum!(IsAuto; Yes No);
341spanless_eq_enum!(LitIntType; Signed(0) Unsigned(0) Unsuffixed);
David Tolnayae019182019-04-24 03:16:48 -0700342spanless_eq_enum!(LocalSource; Normal AsyncFn);
David Tolnayecd024d2018-07-21 09:07:56 -0700343spanless_eq_enum!(MacDelimiter; Parenthesis Bracket Brace);
344spanless_eq_enum!(MacStmtStyle; Semicolon Braces NoBraces);
345spanless_eq_enum!(Movability; Static Movable);
346spanless_eq_enum!(Mutability; Mutable Immutable);
347spanless_eq_enum!(RangeEnd; Included(0) Excluded);
348spanless_eq_enum!(RangeLimits; HalfOpen Closed);
David Tolnayecd024d2018-07-21 09:07:56 -0700349spanless_eq_enum!(StmtKind; Local(0) Item(0) Expr(0) Semi(0) Mac(0));
350spanless_eq_enum!(StrStyle; Cooked Raw(0));
David Tolnaya69aa512018-12-14 23:42:26 -0800351spanless_eq_enum!(TokenTree; Token(0 1) Delimited(0 1 2));
David Tolnayecd024d2018-07-21 09:07:56 -0700352spanless_eq_enum!(TraitBoundModifier; None Maybe);
353spanless_eq_enum!(TraitItemKind; Const(0 1) Method(0 1) Type(0 1) Macro(0));
354spanless_eq_enum!(TraitObjectSyntax; Dyn None);
355spanless_eq_enum!(UintTy; Usize U8 U16 U32 U64 U128);
356spanless_eq_enum!(UnOp; Deref Not Neg);
357spanless_eq_enum!(UnsafeSource; CompilerGenerated UserProvided);
358spanless_eq_enum!(Unsafety; Unsafe Normal);
359spanless_eq_enum!(UseTreeKind; Simple(0 1 2) Nested(0) Glob);
David Tolnay162a5042019-03-26 08:57:26 -0300360spanless_eq_enum!(VariantData; Struct(0 1) Tuple(0 1) Unit(0));
David Tolnayecd024d2018-07-21 09:07:56 -0700361spanless_eq_enum!(VisibilityKind; Public Crate(0) Restricted(path id) Inherited);
362spanless_eq_enum!(WherePredicate; BoundPredicate(0) RegionPredicate(0) EqPredicate(0));
363spanless_eq_enum!(ExprKind; Box(0) ObsoleteInPlace(0 1) Array(0) Call(0 1)
364 MethodCall(0 1) Tup(0) Binary(0 1 2) Unary(0 1) Lit(0) Cast(0 1) Type(0 1)
365 If(0 1 2) IfLet(0 1 2 3) While(0 1 2) WhileLet(0 1 2 3) ForLoop(0 1 2 3)
David Tolnay0db515d2019-05-08 17:58:12 -0700366 Loop(0 1) Match(0 1) Closure(0 1 2 3 4 5) Block(0 1) Async(0 1 2) Await(0 1)
367 TryBlock(0) Assign(0 1) AssignOp(0 1 2) Field(0 1) Index(0 1) Range(0 1 2)
368 Path(0 1) AddrOf(0 1) Break(0 1) Continue(0) Ret(0) InlineAsm(0) Mac(0)
369 Struct(0 1 2) Repeat(0 1) Paren(0) Try(0) Yield(0) Err);
David Tolnayecd024d2018-07-21 09:07:56 -0700370spanless_eq_enum!(ItemKind; ExternCrate(0) Use(0) Static(0 1 2) Const(0 1)
David Tolnay72972e72018-07-21 18:35:24 -0700371 Fn(0 1 2 3) Mod(0) ForeignMod(0) GlobalAsm(0) Ty(0 1) Existential(0 1)
372 Enum(0 1) Struct(0 1) Union(0 1) Trait(0 1 2 3 4) TraitAlias(0 1)
373 Impl(0 1 2 3 4 5 6) Mac(0) MacroDef(0));
David Tolnayecd024d2018-07-21 09:07:56 -0700374spanless_eq_enum!(LitKind; Str(0 1) ByteStr(0) Byte(0) Char(0) Int(0 1)
David Tolnay30ccfe32019-01-20 20:41:20 -0800375 Float(0 1) FloatUnsuffixed(0) Bool(0) Err(0));
David Tolnayecd024d2018-07-21 09:07:56 -0700376spanless_eq_enum!(PatKind; Wild Ident(0 1 2) Struct(0 1 2) TupleStruct(0 1 2)
377 Path(0 1) Tuple(0 1) Box(0) Ref(0 1) Lit(0) Range(0 1 2) Slice(0 1 2)
378 Paren(0) Mac(0));
379spanless_eq_enum!(TyKind; Slice(0) Array(0 1) Ptr(0) Rptr(0 1) BareFn(0) Never
380 Tup(0) Path(0 1) TraitObject(0 1) ImplTrait(0 1) Paren(0) Typeof(0) Infer
Dan Robertsonb7aa8072019-02-08 18:38:27 +0000381 ImplicitSelf Mac(0) Err CVarArgs);
David Tolnayecd024d2018-07-21 09:07:56 -0700382
383impl SpanlessEq for Ident {
384 fn eq(&self, other: &Self) -> bool {
385 self.as_str() == other.as_str()
386 }
387}
388
389// Give up on comparing literals inside of macros because there are so many
390// equivalent representations of the same literal; they are tested elsewhere
David Tolnay2979f982019-05-13 21:04:38 -0700391impl SpanlessEq for token::Lit {
David Tolnayecd024d2018-07-21 09:07:56 -0700392 fn eq(&self, other: &Self) -> bool {
393 mem::discriminant(self) == mem::discriminant(other)
394 }
395}
396
David Tolnayc6b5e812018-07-21 14:04:28 -0700397impl SpanlessEq for RangeSyntax {
398 fn eq(&self, _other: &Self) -> bool {
399 match self {
400 RangeSyntax::DotDotDot | RangeSyntax::DotDotEq => true,
401 }
402 }
403}
404
David Tolnayecd024d2018-07-21 09:07:56 -0700405impl SpanlessEq for Token {
406 fn eq(&self, other: &Self) -> bool {
407 match (self, other) {
408 (Token::Literal(this, _), Token::Literal(other, _)) => SpanlessEq::eq(this, other),
David Tolnayc6b5e812018-07-21 14:04:28 -0700409 (Token::DotDotEq, _) | (Token::DotDotDot, _) => match other {
410 Token::DotDotEq | Token::DotDotDot => true,
411 _ => false,
David Tolnay72972e72018-07-21 18:35:24 -0700412 },
David Tolnayecd024d2018-07-21 09:07:56 -0700413 _ => self == other,
414 }
415 }
416}
417
418impl SpanlessEq for TokenStream {
419 fn eq(&self, other: &Self) -> bool {
420 SpanlessEq::eq(&expand_tts(self), &expand_tts(other))
421 }
422}
423
David Tolnayecd024d2018-07-21 09:07:56 -0700424fn expand_tts(tts: &TokenStream) -> Vec<TokenTree> {
425 let mut tokens = Vec::new();
426 for tt in tts.clone().into_trees() {
427 let c = match tt {
428 TokenTree::Token(_, Token::DocComment(c)) => c,
429 _ => {
430 tokens.push(tt);
431 continue;
432 }
433 };
434 let contents = comments::strip_doc_comment_decoration(&c.as_str());
435 let style = comments::doc_comment_style(&c.as_str());
436 tokens.push(TokenTree::Token(DUMMY_SP, Token::Pound));
437 if style == AttrStyle::Inner {
438 tokens.push(TokenTree::Token(DUMMY_SP, Token::Not));
439 }
David Tolnay2979f982019-05-13 21:04:38 -0700440 let lit = token::Lit::Str_(Symbol::intern(&contents));
David Tolnay44b831c2019-04-24 03:17:50 -0700441 let tts = vec![
David Tolnayecd024d2018-07-21 09:07:56 -0700442 TokenTree::Token(DUMMY_SP, Token::Ident(Ident::from_str("doc"), false)),
443 TokenTree::Token(DUMMY_SP, Token::Eq),
444 TokenTree::Token(DUMMY_SP, Token::Literal(lit, None)),
445 ];
446 tokens.push(TokenTree::Delimited(
David Tolnay2b940f62018-09-09 22:16:07 -0700447 DelimSpan::dummy(),
David Tolnaya69aa512018-12-14 23:42:26 -0800448 DelimToken::Bracket,
449 tts.into_iter().collect::<TokenStream>().into(),
David Tolnayecd024d2018-07-21 09:07:56 -0700450 ));
451 }
452 tokens
453}