blob: c5bfd7cdf05e8b2027d2654d01776c47e4da3c50 [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 Tolnay2c8fc612019-06-04 22:58:00 -070013 AngleBracketedArgs, AnonConst, Arg, Arm, AsmDialect, AttrId, AttrStyle, Attribute, AwaitOrigin,
14 BareFnTy, BinOpKind, BindingMode, Block, BlockCheckMode, CaptureBy, Constness, Crate,
15 CrateSugar, Defaultness, EnumDef, Expr, ExprKind, Field, FieldPat, FnDecl, FnHeader,
16 ForeignItem, ForeignItemKind, ForeignMod, FunctionRetTy, GenericArg, GenericArgs, GenericBound,
17 GenericParam, GenericParamKind, Generics, GlobalAsm, Guard, Ident, ImplItem, ImplItemKind,
18 ImplPolarity, InlineAsm, InlineAsmOutput, IntTy, IsAsync, IsAuto, Item, ItemKind, Label,
19 Lifetime, Lit, LitIntType, LitKind, Local, MacDelimiter, MacStmtStyle, Mac_, MacroDef,
20 MethodSig, Mod, Movability, MutTy, Mutability, NodeId, ParenthesizedArgs, Pat, PatKind, Path,
21 PathSegment, PolyTraitRef, QSelf, RangeEnd, RangeLimits, RangeSyntax, Stmt, StmtKind, StrStyle,
22 StructField, TraitBoundModifier, TraitItem, TraitItemKind, TraitObjectSyntax, TraitRef, Ty,
23 TyKind, TypeBinding, UintTy, UnOp, UnsafeSource, Unsafety, UseTree, UseTreeKind, VariantData,
24 Variant_, VisibilityKind, WhereBoundPredicate, WhereClause, WhereEqPredicate, WherePredicate,
25 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 Tolnay2c8fc612019-06-04 22:58:00 -0700268spanless_eq_struct!(Arg; ty pat id);
David Tolnayb53013e2019-05-23 22:49:14 -0700269spanless_eq_struct!(Arm; attrs pats guard body span);
David Tolnayecd024d2018-07-21 09:07:56 -0700270spanless_eq_struct!(Attribute; id style path tokens span !is_sugared_doc);
271spanless_eq_struct!(BareFnTy; unsafety abi generic_params decl);
David Tolnay5f5d76a2018-12-29 00:20:35 -0500272spanless_eq_struct!(Block; stmts id rules span);
David Tolnayecd024d2018-07-21 09:07:56 -0700273spanless_eq_struct!(Crate; module attrs span);
David Tolnayecd024d2018-07-21 09:07:56 -0700274spanless_eq_struct!(EnumDef; variants);
275spanless_eq_struct!(Expr; id node span attrs);
276spanless_eq_struct!(Field; ident expr span is_shorthand attrs);
277spanless_eq_struct!(FieldPat; ident pat is_shorthand attrs);
Dan Robertsonb7aa8072019-02-08 18:38:27 +0000278spanless_eq_struct!(FnDecl; inputs output c_variadic);
David Tolnayecd024d2018-07-21 09:07:56 -0700279spanless_eq_struct!(FnHeader; unsafety asyncness constness abi);
280spanless_eq_struct!(ForeignItem; ident attrs node id span vis);
281spanless_eq_struct!(ForeignMod; abi items);
282spanless_eq_struct!(GenericParam; id ident attrs bounds kind);
283spanless_eq_struct!(Generics; params where_clause span);
284spanless_eq_struct!(GlobalAsm; asm ctxt);
285spanless_eq_struct!(ImplItem; id ident vis defaultness attrs generics node span !tokens);
286spanless_eq_struct!(InlineAsm; asm asm_str_style outputs inputs clobbers volatile alignstack dialect ctxt);
287spanless_eq_struct!(InlineAsmOutput; constraint expr is_rw is_indirect);
288spanless_eq_struct!(Item; ident attrs id node vis span !tokens);
289spanless_eq_struct!(Label; ident);
290spanless_eq_struct!(Lifetime; id ident);
David Tolnayb53013e2019-05-23 22:49:14 -0700291spanless_eq_struct!(Lit; token node span);
David Tolnay2c8fc612019-06-04 22:58:00 -0700292spanless_eq_struct!(Local; pat ty init id span attrs);
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);
316spanless_eq_enum!(AsmDialect; Att Intel);
317spanless_eq_enum!(AttrStyle; Outer Inner);
David Tolnay0db515d2019-05-08 17:58:12 -0700318spanless_eq_enum!(AwaitOrigin; FieldLike MacroLike);
David Tolnayecd024d2018-07-21 09:07:56 -0700319spanless_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 Tolnay2c8fc612019-06-04 22:58:00 -0700337spanless_eq_enum!(IsAsync; Async(closure_id return_impl_trait_id) NotAsync);
David Tolnayecd024d2018-07-21 09:07:56 -0700338spanless_eq_enum!(IsAuto; Yes No);
339spanless_eq_enum!(LitIntType; Signed(0) Unsigned(0) Unsuffixed);
340spanless_eq_enum!(MacDelimiter; Parenthesis Bracket Brace);
341spanless_eq_enum!(MacStmtStyle; Semicolon Braces NoBraces);
342spanless_eq_enum!(Movability; Static Movable);
343spanless_eq_enum!(Mutability; Mutable Immutable);
344spanless_eq_enum!(RangeEnd; Included(0) Excluded);
345spanless_eq_enum!(RangeLimits; HalfOpen Closed);
David Tolnayecd024d2018-07-21 09:07:56 -0700346spanless_eq_enum!(StmtKind; Local(0) Item(0) Expr(0) Semi(0) Mac(0));
347spanless_eq_enum!(StrStyle; Cooked Raw(0));
David Tolnaya69aa512018-12-14 23:42:26 -0800348spanless_eq_enum!(TokenTree; Token(0 1) Delimited(0 1 2));
David Tolnayecd024d2018-07-21 09:07:56 -0700349spanless_eq_enum!(TraitBoundModifier; None Maybe);
350spanless_eq_enum!(TraitItemKind; Const(0 1) Method(0 1) Type(0 1) Macro(0));
351spanless_eq_enum!(TraitObjectSyntax; Dyn None);
352spanless_eq_enum!(UintTy; Usize U8 U16 U32 U64 U128);
353spanless_eq_enum!(UnOp; Deref Not Neg);
354spanless_eq_enum!(UnsafeSource; CompilerGenerated UserProvided);
355spanless_eq_enum!(Unsafety; Unsafe Normal);
356spanless_eq_enum!(UseTreeKind; Simple(0 1 2) Nested(0) Glob);
David Tolnay162a5042019-03-26 08:57:26 -0300357spanless_eq_enum!(VariantData; Struct(0 1) Tuple(0 1) Unit(0));
David Tolnayecd024d2018-07-21 09:07:56 -0700358spanless_eq_enum!(VisibilityKind; Public Crate(0) Restricted(path id) Inherited);
359spanless_eq_enum!(WherePredicate; BoundPredicate(0) RegionPredicate(0) EqPredicate(0));
David Tolnay1150d032019-05-25 00:05:38 -0700360spanless_eq_enum!(ExprKind; Box(0) Array(0) Call(0 1) MethodCall(0 1) Tup(0)
361 Binary(0 1 2) Unary(0 1) Lit(0) Cast(0 1) Type(0 1) If(0 1 2) IfLet(0 1 2 3)
362 While(0 1 2) WhileLet(0 1 2 3) ForLoop(0 1 2 3) Loop(0 1) Match(0 1)
363 Closure(0 1 2 3 4 5) Block(0 1) Async(0 1 2) Await(0 1) TryBlock(0)
364 Assign(0 1) AssignOp(0 1 2) Field(0 1) Index(0 1) Range(0 1 2) Path(0 1)
365 AddrOf(0 1) Break(0 1) Continue(0) Ret(0) InlineAsm(0) Mac(0) Struct(0 1 2)
366 Repeat(0 1) Paren(0) Try(0) Yield(0) Err);
David Tolnayecd024d2018-07-21 09:07:56 -0700367spanless_eq_enum!(ItemKind; ExternCrate(0) Use(0) Static(0 1 2) Const(0 1)
David Tolnay72972e72018-07-21 18:35:24 -0700368 Fn(0 1 2 3) Mod(0) ForeignMod(0) GlobalAsm(0) Ty(0 1) Existential(0 1)
369 Enum(0 1) Struct(0 1) Union(0 1) Trait(0 1 2 3 4) TraitAlias(0 1)
370 Impl(0 1 2 3 4 5 6) Mac(0) MacroDef(0));
David Tolnayecd024d2018-07-21 09:07:56 -0700371spanless_eq_enum!(LitKind; Str(0 1) ByteStr(0) Byte(0) Char(0) Int(0 1)
David Tolnay30ccfe32019-01-20 20:41:20 -0800372 Float(0 1) FloatUnsuffixed(0) Bool(0) Err(0));
David Tolnayecd024d2018-07-21 09:07:56 -0700373spanless_eq_enum!(PatKind; Wild Ident(0 1 2) Struct(0 1 2) TupleStruct(0 1 2)
374 Path(0 1) Tuple(0 1) Box(0) Ref(0 1) Lit(0) Range(0 1 2) Slice(0 1 2)
375 Paren(0) Mac(0));
376spanless_eq_enum!(TyKind; Slice(0) Array(0 1) Ptr(0) Rptr(0 1) BareFn(0) Never
377 Tup(0) Path(0 1) TraitObject(0 1) ImplTrait(0 1) Paren(0) Typeof(0) Infer
Dan Robertsonb7aa8072019-02-08 18:38:27 +0000378 ImplicitSelf Mac(0) Err CVarArgs);
David Tolnayecd024d2018-07-21 09:07:56 -0700379
380impl SpanlessEq for Ident {
381 fn eq(&self, other: &Self) -> bool {
382 self.as_str() == other.as_str()
383 }
384}
385
386// Give up on comparing literals inside of macros because there are so many
387// equivalent representations of the same literal; they are tested elsewhere
David Tolnay2979f982019-05-13 21:04:38 -0700388impl SpanlessEq for token::Lit {
David Tolnayecd024d2018-07-21 09:07:56 -0700389 fn eq(&self, other: &Self) -> bool {
390 mem::discriminant(self) == mem::discriminant(other)
391 }
392}
393
David Tolnayc6b5e812018-07-21 14:04:28 -0700394impl SpanlessEq for RangeSyntax {
395 fn eq(&self, _other: &Self) -> bool {
396 match self {
397 RangeSyntax::DotDotDot | RangeSyntax::DotDotEq => true,
398 }
399 }
400}
401
David Tolnayecd024d2018-07-21 09:07:56 -0700402impl SpanlessEq for Token {
403 fn eq(&self, other: &Self) -> bool {
404 match (self, other) {
David Tolnayb53013e2019-05-23 22:49:14 -0700405 (Token::Literal(this), Token::Literal(other)) => SpanlessEq::eq(this, other),
David Tolnayc6b5e812018-07-21 14:04:28 -0700406 (Token::DotDotEq, _) | (Token::DotDotDot, _) => match other {
407 Token::DotDotEq | Token::DotDotDot => true,
408 _ => false,
David Tolnay72972e72018-07-21 18:35:24 -0700409 },
David Tolnayecd024d2018-07-21 09:07:56 -0700410 _ => self == other,
411 }
412 }
413}
414
415impl SpanlessEq for TokenStream {
416 fn eq(&self, other: &Self) -> bool {
417 SpanlessEq::eq(&expand_tts(self), &expand_tts(other))
418 }
419}
420
David Tolnayecd024d2018-07-21 09:07:56 -0700421fn expand_tts(tts: &TokenStream) -> Vec<TokenTree> {
422 let mut tokens = Vec::new();
423 for tt in tts.clone().into_trees() {
424 let c = match tt {
425 TokenTree::Token(_, Token::DocComment(c)) => c,
426 _ => {
427 tokens.push(tt);
428 continue;
429 }
430 };
431 let contents = comments::strip_doc_comment_decoration(&c.as_str());
432 let style = comments::doc_comment_style(&c.as_str());
433 tokens.push(TokenTree::Token(DUMMY_SP, Token::Pound));
434 if style == AttrStyle::Inner {
435 tokens.push(TokenTree::Token(DUMMY_SP, Token::Not));
436 }
David Tolnayb53013e2019-05-23 22:49:14 -0700437 let lit = token::Lit {
438 kind: token::LitKind::Str,
439 symbol: Symbol::intern(&contents),
440 suffix: None,
441 };
David Tolnay44b831c2019-04-24 03:17:50 -0700442 let tts = vec![
David Tolnayecd024d2018-07-21 09:07:56 -0700443 TokenTree::Token(DUMMY_SP, Token::Ident(Ident::from_str("doc"), false)),
444 TokenTree::Token(DUMMY_SP, Token::Eq),
David Tolnayb53013e2019-05-23 22:49:14 -0700445 TokenTree::Token(DUMMY_SP, Token::Literal(lit)),
David Tolnayecd024d2018-07-21 09:07:56 -0700446 ];
447 tokens.push(TokenTree::Delimited(
David Tolnay2b940f62018-09-09 22:16:07 -0700448 DelimSpan::dummy(),
David Tolnaya69aa512018-12-14 23:42:26 -0800449 DelimToken::Bracket,
450 tts.into_iter().collect::<TokenStream>().into(),
David Tolnayecd024d2018-07-21 09:07:56 -0700451 ));
452 }
453 tokens
454}