blob: 4a882bb9bd35c170fb7ff87d778d855432731ce0 [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,
14 AttrStyle, Attribute, BareFnTy, BinOpKind, BindingMode, Block, BlockCheckMode, CaptureBy,
15 Constness, Crate, CrateSugar, Defaultness, EnumDef, Expr, ExprKind, Field, FieldPat, FnDecl,
16 FnHeader, ForeignItem, ForeignItemKind, ForeignMod, FunctionRetTy, GenericArg, GenericArgs,
17 GenericBound, GenericParam, GenericParamKind, Generics, GlobalAsm, Guard, Ident, ImplItem,
18 ImplItemKind, ImplPolarity, InlineAsm, InlineAsmOutput, IntTy, IsAsync, IsAuto, Item, ItemKind,
19 Label, Lifetime, LitIntType, LitKind, Local, LocalSource, MacDelimiter, MacStmtStyle, Mac_,
20 MacroDef, MethodSig, Mod, Movability, MutTy, Mutability, NodeId, ParenthesizedArgs, Pat,
21 PatKind, Path, PathSegment, PolyTraitRef, QSelf, RangeEnd, RangeLimits, RangeSyntax, Stmt,
22 StmtKind, StrStyle, StructField, TraitBoundModifier, TraitItem, TraitItemKind,
23 TraitObjectSyntax, TraitRef, Ty, TyKind, TypeBinding, UintTy, UnOp, UnsafeSource, Unsafety,
24 UseTree, UseTreeKind, VariantData, Variant_, VisibilityKind, WhereBoundPredicate, WhereClause,
25 WhereEqPredicate, WherePredicate, WhereRegionPredicate,
David Tolnayecd024d2018-07-21 09:07:56 -070026};
David Tolnayecd024d2018-07-21 09:07:56 -070027use self::syntax::parse::lexer::comments;
28use self::syntax::parse::token::{DelimToken, Lit, Token};
29use 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 Tolnayae019182019-04-24 03:16:48 -0700270spanless_eq_struct!(AsyncArgument; ident arg 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 Tolnayae019182019-04-24 03:16:48 -0700292spanless_eq_struct!(Local; pat ty init id span attrs source);
David Tolnayecd024d2018-07-21 09:07:56 -0700293spanless_eq_struct!(Mac_; path delim tts);
294spanless_eq_struct!(MacroDef; tokens legacy);
295spanless_eq_struct!(MethodSig; header decl);
David Tolnay35cb3402018-09-27 22:38:19 -0700296spanless_eq_struct!(Mod; inner items inline);
David Tolnayecd024d2018-07-21 09:07:56 -0700297spanless_eq_struct!(MutTy; ty mutbl);
David Tolnayd54cc9b2019-01-22 21:53:44 -0800298spanless_eq_struct!(ParenthesizedArgs; span inputs output);
David Tolnayecd024d2018-07-21 09:07:56 -0700299spanless_eq_struct!(Pat; id node span);
300spanless_eq_struct!(Path; span segments);
David Tolnay41280d82018-10-27 21:22:02 -0700301spanless_eq_struct!(PathSegment; ident id args);
David Tolnayecd024d2018-07-21 09:07:56 -0700302spanless_eq_struct!(PolyTraitRef; bound_generic_params trait_ref span);
303spanless_eq_struct!(QSelf; ty path_span position);
304spanless_eq_struct!(Stmt; id node span);
305spanless_eq_struct!(StructField; span ident vis id ty attrs);
306spanless_eq_struct!(TraitItem; id ident attrs generics node span !tokens);
307spanless_eq_struct!(TraitRef; path ref_id);
308spanless_eq_struct!(Ty; id node span);
309spanless_eq_struct!(TypeBinding; id ident ty span);
310spanless_eq_struct!(UseTree; prefix kind span);
David Tolnay162a5042019-03-26 08:57:26 -0300311spanless_eq_struct!(Variant_; ident attrs id data disr_expr);
David Tolnayecd024d2018-07-21 09:07:56 -0700312spanless_eq_struct!(WhereBoundPredicate; span bound_generic_params bounded_ty bounds);
313spanless_eq_struct!(WhereClause; id predicates span);
314spanless_eq_struct!(WhereEqPredicate; id span lhs_ty rhs_ty);
315spanless_eq_struct!(WhereRegionPredicate; span lifetime bounds);
David Tolnayae019182019-04-24 03:16:48 -0700316spanless_eq_enum!(ArgSource; Normal AsyncFn(0));
David Tolnayecd024d2018-07-21 09:07:56 -0700317spanless_eq_enum!(AsmDialect; Att Intel);
318spanless_eq_enum!(AttrStyle; Outer Inner);
319spanless_eq_enum!(BinOpKind; Add Sub Mul Div Rem And Or BitXor BitAnd BitOr Shl Shr Eq Lt Le Ne Ge Gt);
320spanless_eq_enum!(BindingMode; ByRef(0) ByValue(0));
321spanless_eq_enum!(BlockCheckMode; Default Unsafe(0));
322spanless_eq_enum!(CaptureBy; Value Ref);
323spanless_eq_enum!(Constness; Const NotConst);
324spanless_eq_enum!(CrateSugar; PubCrate JustCrate);
325spanless_eq_enum!(Defaultness; Default Final);
326spanless_eq_enum!(FloatTy; F32 F64);
327spanless_eq_enum!(ForeignItemKind; Fn(0 1) Static(0 1) Ty Macro(0));
328spanless_eq_enum!(FunctionRetTy; Default(0) Ty(0));
David Tolnay9f788452019-02-09 16:00:37 +0100329spanless_eq_enum!(GenericArg; Lifetime(0) Type(0) Const(0));
David Tolnayecd024d2018-07-21 09:07:56 -0700330spanless_eq_enum!(GenericArgs; AngleBracketed(0) Parenthesized(0));
331spanless_eq_enum!(GenericBound; Trait(0 1) Outlives(0));
David Tolnay9f788452019-02-09 16:00:37 +0100332spanless_eq_enum!(GenericParamKind; Lifetime Type(default) Const(ty));
David Tolnay83c89012018-09-01 18:15:53 -0700333spanless_eq_enum!(Guard; If(0));
David Tolnay72972e72018-07-21 18:35:24 -0700334spanless_eq_enum!(ImplItemKind; Const(0 1) Method(0 1) Type(0) Existential(0) Macro(0));
David Tolnayecd024d2018-07-21 09:07:56 -0700335spanless_eq_enum!(ImplPolarity; Positive Negative);
336spanless_eq_enum!(IntTy; Isize I8 I16 I32 I64 I128);
David Tolnayae019182019-04-24 03:16:48 -0700337spanless_eq_enum!(IsAsync; Async(closure_id return_impl_trait_id arguments) NotAsync);
David Tolnayecd024d2018-07-21 09:07:56 -0700338spanless_eq_enum!(IsAuto; Yes No);
339spanless_eq_enum!(LitIntType; Signed(0) Unsigned(0) Unsuffixed);
David Tolnayae019182019-04-24 03:16:48 -0700340spanless_eq_enum!(LocalSource; Normal AsyncFn);
David Tolnayecd024d2018-07-21 09:07:56 -0700341spanless_eq_enum!(MacDelimiter; Parenthesis Bracket Brace);
342spanless_eq_enum!(MacStmtStyle; Semicolon Braces NoBraces);
343spanless_eq_enum!(Movability; Static Movable);
344spanless_eq_enum!(Mutability; Mutable Immutable);
345spanless_eq_enum!(RangeEnd; Included(0) Excluded);
346spanless_eq_enum!(RangeLimits; HalfOpen Closed);
David Tolnayecd024d2018-07-21 09:07:56 -0700347spanless_eq_enum!(StmtKind; Local(0) Item(0) Expr(0) Semi(0) Mac(0));
348spanless_eq_enum!(StrStyle; Cooked Raw(0));
David Tolnaya69aa512018-12-14 23:42:26 -0800349spanless_eq_enum!(TokenTree; Token(0 1) Delimited(0 1 2));
David Tolnayecd024d2018-07-21 09:07:56 -0700350spanless_eq_enum!(TraitBoundModifier; None Maybe);
351spanless_eq_enum!(TraitItemKind; Const(0 1) Method(0 1) Type(0 1) Macro(0));
352spanless_eq_enum!(TraitObjectSyntax; Dyn None);
353spanless_eq_enum!(UintTy; Usize U8 U16 U32 U64 U128);
354spanless_eq_enum!(UnOp; Deref Not Neg);
355spanless_eq_enum!(UnsafeSource; CompilerGenerated UserProvided);
356spanless_eq_enum!(Unsafety; Unsafe Normal);
357spanless_eq_enum!(UseTreeKind; Simple(0 1 2) Nested(0) Glob);
David Tolnay162a5042019-03-26 08:57:26 -0300358spanless_eq_enum!(VariantData; Struct(0 1) Tuple(0 1) Unit(0));
David Tolnayecd024d2018-07-21 09:07:56 -0700359spanless_eq_enum!(VisibilityKind; Public Crate(0) Restricted(path id) Inherited);
360spanless_eq_enum!(WherePredicate; BoundPredicate(0) RegionPredicate(0) EqPredicate(0));
361spanless_eq_enum!(ExprKind; Box(0) ObsoleteInPlace(0 1) Array(0) Call(0 1)
362 MethodCall(0 1) Tup(0) Binary(0 1 2) Unary(0 1) Lit(0) Cast(0 1) Type(0 1)
363 If(0 1 2) IfLet(0 1 2 3) While(0 1 2) WhileLet(0 1 2 3) ForLoop(0 1 2 3)
David Tolnayd1c31cc2018-08-24 14:47:15 -0400364 Loop(0 1) Match(0 1) Closure(0 1 2 3 4 5) Block(0 1) Async(0 1 2) TryBlock(0)
David Tolnayecd024d2018-07-21 09:07:56 -0700365 Assign(0 1) AssignOp(0 1 2) Field(0 1) Index(0 1) Range(0 1 2) Path(0 1)
366 AddrOf(0 1) Break(0 1) Continue(0) Ret(0) InlineAsm(0) Mac(0) Struct(0 1 2)
David Tolnay5f5d76a2018-12-29 00:20:35 -0500367 Repeat(0 1) Paren(0) Try(0) Yield(0) Err);
David Tolnayecd024d2018-07-21 09:07:56 -0700368spanless_eq_enum!(ItemKind; ExternCrate(0) Use(0) Static(0 1 2) Const(0 1)
David Tolnay72972e72018-07-21 18:35:24 -0700369 Fn(0 1 2 3) Mod(0) ForeignMod(0) GlobalAsm(0) Ty(0 1) Existential(0 1)
370 Enum(0 1) Struct(0 1) Union(0 1) Trait(0 1 2 3 4) TraitAlias(0 1)
371 Impl(0 1 2 3 4 5 6) Mac(0) MacroDef(0));
David Tolnayecd024d2018-07-21 09:07:56 -0700372spanless_eq_enum!(LitKind; Str(0 1) ByteStr(0) Byte(0) Char(0) Int(0 1)
David Tolnay30ccfe32019-01-20 20:41:20 -0800373 Float(0 1) FloatUnsuffixed(0) Bool(0) Err(0));
David Tolnayecd024d2018-07-21 09:07:56 -0700374spanless_eq_enum!(PatKind; Wild Ident(0 1 2) Struct(0 1 2) TupleStruct(0 1 2)
375 Path(0 1) Tuple(0 1) Box(0) Ref(0 1) Lit(0) Range(0 1 2) Slice(0 1 2)
376 Paren(0) Mac(0));
377spanless_eq_enum!(TyKind; Slice(0) Array(0 1) Ptr(0) Rptr(0 1) BareFn(0) Never
378 Tup(0) Path(0 1) TraitObject(0 1) ImplTrait(0 1) Paren(0) Typeof(0) Infer
Dan Robertsonb7aa8072019-02-08 18:38:27 +0000379 ImplicitSelf Mac(0) Err CVarArgs);
David Tolnayecd024d2018-07-21 09:07:56 -0700380
381impl SpanlessEq for Ident {
382 fn eq(&self, other: &Self) -> bool {
383 self.as_str() == other.as_str()
384 }
385}
386
387// Give up on comparing literals inside of macros because there are so many
388// equivalent representations of the same literal; they are tested elsewhere
389impl SpanlessEq for Lit {
390 fn eq(&self, other: &Self) -> bool {
391 mem::discriminant(self) == mem::discriminant(other)
392 }
393}
394
David Tolnayc6b5e812018-07-21 14:04:28 -0700395impl SpanlessEq for RangeSyntax {
396 fn eq(&self, _other: &Self) -> bool {
397 match self {
398 RangeSyntax::DotDotDot | RangeSyntax::DotDotEq => true,
399 }
400 }
401}
402
David Tolnayecd024d2018-07-21 09:07:56 -0700403impl SpanlessEq for Token {
404 fn eq(&self, other: &Self) -> bool {
405 match (self, other) {
406 (Token::Literal(this, _), Token::Literal(other, _)) => SpanlessEq::eq(this, other),
David Tolnayc6b5e812018-07-21 14:04:28 -0700407 (Token::DotDotEq, _) | (Token::DotDotDot, _) => match other {
408 Token::DotDotEq | Token::DotDotDot => true,
409 _ => false,
David Tolnay72972e72018-07-21 18:35:24 -0700410 },
David Tolnayecd024d2018-07-21 09:07:56 -0700411 _ => self == other,
412 }
413 }
414}
415
416impl SpanlessEq for TokenStream {
417 fn eq(&self, other: &Self) -> bool {
418 SpanlessEq::eq(&expand_tts(self), &expand_tts(other))
419 }
420}
421
David Tolnayecd024d2018-07-21 09:07:56 -0700422fn expand_tts(tts: &TokenStream) -> Vec<TokenTree> {
423 let mut tokens = Vec::new();
424 for tt in tts.clone().into_trees() {
425 let c = match tt {
426 TokenTree::Token(_, Token::DocComment(c)) => c,
427 _ => {
428 tokens.push(tt);
429 continue;
430 }
431 };
432 let contents = comments::strip_doc_comment_decoration(&c.as_str());
433 let style = comments::doc_comment_style(&c.as_str());
434 tokens.push(TokenTree::Token(DUMMY_SP, Token::Pound));
435 if style == AttrStyle::Inner {
436 tokens.push(TokenTree::Token(DUMMY_SP, Token::Not));
437 }
438 let lit = Lit::Str_(Symbol::intern(&contents));
439 let mut tts = vec![
440 TokenTree::Token(DUMMY_SP, Token::Ident(Ident::from_str("doc"), false)),
441 TokenTree::Token(DUMMY_SP, Token::Eq),
442 TokenTree::Token(DUMMY_SP, Token::Literal(lit, None)),
443 ];
444 tokens.push(TokenTree::Delimited(
David Tolnay2b940f62018-09-09 22:16:07 -0700445 DelimSpan::dummy(),
David Tolnaya69aa512018-12-14 23:42:26 -0800446 DelimToken::Bracket,
447 tts.into_iter().collect::<TokenStream>().into(),
David Tolnayecd024d2018-07-21 09:07:56 -0700448 ));
449 }
450 tokens
451}