]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_ast/src/attr/mod.rs
07f982b7e864bb3181f2917077b77a478ce7e662
[rust.git] / compiler / rustc_ast / src / attr / mod.rs
1 //! Functions dealing with attributes and meta items.
2
3 use crate::ast;
4 use crate::ast::{AttrId, AttrItem, AttrKind, AttrStyle, Attribute};
5 use crate::ast::{Lit, LitKind};
6 use crate::ast::{MacArgs, MacArgsEq, MacDelimiter, MetaItem, MetaItemKind, NestedMetaItem};
7 use crate::ast::{Path, PathSegment};
8 use crate::ptr::P;
9 use crate::token::{self, CommentKind, Delimiter, Token};
10 use crate::tokenstream::{DelimSpan, Spacing, TokenTree};
11 use crate::tokenstream::{LazyAttrTokenStream, TokenStream};
12 use crate::util::comments;
13
14 use rustc_data_structures::sync::WorkerLocal;
15 use rustc_index::bit_set::GrowableBitSet;
16 use rustc_span::source_map::BytePos;
17 use rustc_span::symbol::{sym, Ident, Symbol};
18 use rustc_span::Span;
19
20 use std::cell::Cell;
21 use std::iter;
22 #[cfg(debug_assertions)]
23 use std::ops::BitXor;
24 #[cfg(debug_assertions)]
25 use std::sync::atomic::{AtomicU32, Ordering};
26
27 pub struct MarkedAttrs(GrowableBitSet<AttrId>);
28
29 impl MarkedAttrs {
30     // We have no idea how many attributes there will be, so just
31     // initiate the vectors with 0 bits. We'll grow them as necessary.
32     pub fn new() -> Self {
33         MarkedAttrs(GrowableBitSet::new_empty())
34     }
35
36     pub fn mark(&mut self, attr: &Attribute) {
37         self.0.insert(attr.id);
38     }
39
40     pub fn is_marked(&self, attr: &Attribute) -> bool {
41         self.0.contains(attr.id)
42     }
43 }
44
45 impl NestedMetaItem {
46     /// Returns the `MetaItem` if `self` is a `NestedMetaItem::MetaItem`.
47     pub fn meta_item(&self) -> Option<&MetaItem> {
48         match *self {
49             NestedMetaItem::MetaItem(ref item) => Some(item),
50             _ => None,
51         }
52     }
53
54     /// Returns the `Lit` if `self` is a `NestedMetaItem::Literal`s.
55     pub fn literal(&self) -> Option<&Lit> {
56         match *self {
57             NestedMetaItem::Literal(ref lit) => Some(lit),
58             _ => None,
59         }
60     }
61
62     /// Returns `true` if this list item is a MetaItem with a name of `name`.
63     pub fn has_name(&self, name: Symbol) -> bool {
64         self.meta_item().map_or(false, |meta_item| meta_item.has_name(name))
65     }
66
67     /// For a single-segment meta item, returns its name; otherwise, returns `None`.
68     pub fn ident(&self) -> Option<Ident> {
69         self.meta_item().and_then(|meta_item| meta_item.ident())
70     }
71     pub fn name_or_empty(&self) -> Symbol {
72         self.ident().unwrap_or_else(Ident::empty).name
73     }
74
75     /// Gets the string value if `self` is a `MetaItem` and the `MetaItem` is a
76     /// `MetaItemKind::NameValue` variant containing a string, otherwise `None`.
77     pub fn value_str(&self) -> Option<Symbol> {
78         self.meta_item().and_then(|meta_item| meta_item.value_str())
79     }
80
81     /// Returns a name and single literal value tuple of the `MetaItem`.
82     pub fn name_value_literal(&self) -> Option<(Symbol, &Lit)> {
83         self.meta_item().and_then(|meta_item| {
84             meta_item.meta_item_list().and_then(|meta_item_list| {
85                 if meta_item_list.len() == 1
86                     && let Some(ident) = meta_item.ident()
87                     && let Some(lit) = meta_item_list[0].literal()
88                 {
89                     return Some((ident.name, lit));
90                 }
91                 None
92             })
93         })
94     }
95
96     /// Gets a list of inner meta items from a list `MetaItem` type.
97     pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> {
98         self.meta_item().and_then(|meta_item| meta_item.meta_item_list())
99     }
100
101     /// Returns `true` if the variant is `MetaItem`.
102     pub fn is_meta_item(&self) -> bool {
103         self.meta_item().is_some()
104     }
105
106     /// Returns `true` if `self` is a `MetaItem` and the meta item is a word.
107     pub fn is_word(&self) -> bool {
108         self.meta_item().map_or(false, |meta_item| meta_item.is_word())
109     }
110
111     /// See [`MetaItem::name_value_literal_span`].
112     pub fn name_value_literal_span(&self) -> Option<Span> {
113         self.meta_item()?.name_value_literal_span()
114     }
115 }
116
117 impl Attribute {
118     #[inline]
119     pub fn has_name(&self, name: Symbol) -> bool {
120         match self.kind {
121             AttrKind::Normal(ref normal) => normal.item.path == name,
122             AttrKind::DocComment(..) => false,
123         }
124     }
125
126     /// For a single-segment attribute, returns its name; otherwise, returns `None`.
127     pub fn ident(&self) -> Option<Ident> {
128         match self.kind {
129             AttrKind::Normal(ref normal) => {
130                 if normal.item.path.segments.len() == 1 {
131                     Some(normal.item.path.segments[0].ident)
132                 } else {
133                     None
134                 }
135             }
136             AttrKind::DocComment(..) => None,
137         }
138     }
139     pub fn name_or_empty(&self) -> Symbol {
140         self.ident().unwrap_or_else(Ident::empty).name
141     }
142
143     pub fn value_str(&self) -> Option<Symbol> {
144         match self.kind {
145             AttrKind::Normal(ref normal) => {
146                 normal.item.meta_kind().and_then(|kind| kind.value_str())
147             }
148             AttrKind::DocComment(..) => None,
149         }
150     }
151
152     pub fn meta_item_list(&self) -> Option<Vec<NestedMetaItem>> {
153         match self.kind {
154             AttrKind::Normal(ref normal) => match normal.item.meta_kind() {
155                 Some(MetaItemKind::List(list)) => Some(list),
156                 _ => None,
157             },
158             AttrKind::DocComment(..) => None,
159         }
160     }
161
162     pub fn is_word(&self) -> bool {
163         if let AttrKind::Normal(normal) = &self.kind {
164             matches!(normal.item.args, MacArgs::Empty)
165         } else {
166             false
167         }
168     }
169 }
170
171 impl MetaItem {
172     /// For a single-segment meta item, returns its name; otherwise, returns `None`.
173     pub fn ident(&self) -> Option<Ident> {
174         if self.path.segments.len() == 1 { Some(self.path.segments[0].ident) } else { None }
175     }
176     pub fn name_or_empty(&self) -> Symbol {
177         self.ident().unwrap_or_else(Ident::empty).name
178     }
179
180     // Example:
181     //     #[attribute(name = "value")]
182     //                 ^^^^^^^^^^^^^^
183     pub fn name_value_literal(&self) -> Option<&Lit> {
184         match &self.kind {
185             MetaItemKind::NameValue(v) => Some(v),
186             _ => None,
187         }
188     }
189
190     pub fn value_str(&self) -> Option<Symbol> {
191         self.kind.value_str()
192     }
193
194     pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> {
195         match self.kind {
196             MetaItemKind::List(ref l) => Some(&l[..]),
197             _ => None,
198         }
199     }
200
201     pub fn is_word(&self) -> bool {
202         matches!(self.kind, MetaItemKind::Word)
203     }
204
205     pub fn has_name(&self, name: Symbol) -> bool {
206         self.path == name
207     }
208
209     /// This is used in case you want the value span instead of the whole attribute. Example:
210     ///
211     /// ```text
212     /// #[doc(alias = "foo")]
213     /// ```
214     ///
215     /// In here, it'll return a span for `"foo"`.
216     pub fn name_value_literal_span(&self) -> Option<Span> {
217         Some(self.name_value_literal()?.span)
218     }
219 }
220
221 impl AttrItem {
222     pub fn span(&self) -> Span {
223         self.args.span().map_or(self.path.span, |args_span| self.path.span.to(args_span))
224     }
225
226     pub fn meta(&self, span: Span) -> Option<MetaItem> {
227         Some(MetaItem {
228             path: self.path.clone(),
229             kind: MetaItemKind::from_mac_args(&self.args)?,
230             span,
231         })
232     }
233
234     pub fn meta_kind(&self) -> Option<MetaItemKind> {
235         MetaItemKind::from_mac_args(&self.args)
236     }
237 }
238
239 impl Attribute {
240     /// Returns `true` if it is a sugared doc comment (`///` or `//!` for example).
241     /// So `#[doc = "doc"]` (which is a doc comment) and `#[doc(...)]` (which is not
242     /// a doc comment) will return `false`.
243     pub fn is_doc_comment(&self) -> bool {
244         match self.kind {
245             AttrKind::Normal(..) => false,
246             AttrKind::DocComment(..) => true,
247         }
248     }
249
250     /// Returns the documentation and its kind if this is a doc comment or a sugared doc comment.
251     /// * `///doc` returns `Some(("doc", CommentKind::Line))`.
252     /// * `/** doc */` returns `Some(("doc", CommentKind::Block))`.
253     /// * `#[doc = "doc"]` returns `Some(("doc", CommentKind::Line))`.
254     /// * `#[doc(...)]` returns `None`.
255     pub fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> {
256         match self.kind {
257             AttrKind::DocComment(kind, data) => Some((data, kind)),
258             AttrKind::Normal(ref normal) if normal.item.path == sym::doc => normal
259                 .item
260                 .meta_kind()
261                 .and_then(|kind| kind.value_str())
262                 .map(|data| (data, CommentKind::Line)),
263             _ => None,
264         }
265     }
266
267     /// Returns the documentation if this is a doc comment or a sugared doc comment.
268     /// * `///doc` returns `Some("doc")`.
269     /// * `#[doc = "doc"]` returns `Some("doc")`.
270     /// * `#[doc(...)]` returns `None`.
271     pub fn doc_str(&self) -> Option<Symbol> {
272         match self.kind {
273             AttrKind::DocComment(.., data) => Some(data),
274             AttrKind::Normal(ref normal) if normal.item.path == sym::doc => {
275                 normal.item.meta_kind().and_then(|kind| kind.value_str())
276             }
277             _ => None,
278         }
279     }
280
281     pub fn may_have_doc_links(&self) -> bool {
282         self.doc_str().map_or(false, |s| comments::may_have_doc_links(s.as_str()))
283     }
284
285     pub fn get_normal_item(&self) -> &AttrItem {
286         match self.kind {
287             AttrKind::Normal(ref normal) => &normal.item,
288             AttrKind::DocComment(..) => panic!("unexpected doc comment"),
289         }
290     }
291
292     pub fn unwrap_normal_item(self) -> AttrItem {
293         match self.kind {
294             AttrKind::Normal(normal) => normal.into_inner().item,
295             AttrKind::DocComment(..) => panic!("unexpected doc comment"),
296         }
297     }
298
299     /// Extracts the MetaItem from inside this Attribute.
300     pub fn meta(&self) -> Option<MetaItem> {
301         match self.kind {
302             AttrKind::Normal(ref normal) => normal.item.meta(self.span),
303             AttrKind::DocComment(..) => None,
304         }
305     }
306
307     pub fn meta_kind(&self) -> Option<MetaItemKind> {
308         match self.kind {
309             AttrKind::Normal(ref normal) => normal.item.meta_kind(),
310             AttrKind::DocComment(..) => None,
311         }
312     }
313
314     pub fn tokens(&self) -> TokenStream {
315         match self.kind {
316             AttrKind::Normal(ref normal) => normal
317                 .tokens
318                 .as_ref()
319                 .unwrap_or_else(|| panic!("attribute is missing tokens: {:?}", self))
320                 .to_attr_token_stream()
321                 .to_tokenstream(),
322             AttrKind::DocComment(comment_kind, data) => TokenStream::new(vec![TokenTree::Token(
323                 Token::new(token::DocComment(comment_kind, self.style, data), self.span),
324                 Spacing::Alone,
325             )]),
326         }
327     }
328 }
329
330 /* Constructors */
331
332 pub fn mk_name_value_item_str(ident: Ident, str: Symbol, str_span: Span) -> MetaItem {
333     let lit_kind = LitKind::Str(str, ast::StrStyle::Cooked);
334     mk_name_value_item(ident, lit_kind, str_span)
335 }
336
337 pub fn mk_name_value_item(ident: Ident, lit_kind: LitKind, lit_span: Span) -> MetaItem {
338     let lit = Lit::from_lit_kind(lit_kind, lit_span);
339     let span = ident.span.to(lit_span);
340     MetaItem { path: Path::from_ident(ident), span, kind: MetaItemKind::NameValue(lit) }
341 }
342
343 pub fn mk_list_item(ident: Ident, items: Vec<NestedMetaItem>) -> MetaItem {
344     MetaItem { path: Path::from_ident(ident), span: ident.span, kind: MetaItemKind::List(items) }
345 }
346
347 pub fn mk_word_item(ident: Ident) -> MetaItem {
348     MetaItem { path: Path::from_ident(ident), span: ident.span, kind: MetaItemKind::Word }
349 }
350
351 pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem {
352     NestedMetaItem::MetaItem(mk_word_item(ident))
353 }
354
355 pub struct AttrIdGenerator(WorkerLocal<Cell<u32>>);
356
357 #[cfg(debug_assertions)]
358 static MAX_ATTR_ID: AtomicU32 = AtomicU32::new(u32::MAX);
359
360 impl AttrIdGenerator {
361     pub fn new() -> Self {
362         // We use `(index as u32).reverse_bits()` to initialize the
363         // starting value of AttrId in each worker thread.
364         // The `index` is the index of the worker thread.
365         // This ensures that the AttrId generated in each thread is unique.
366         AttrIdGenerator(WorkerLocal::new(|index| {
367             let index: u32 = index.try_into().unwrap();
368
369             #[cfg(debug_assertions)]
370             {
371                 let max_id = ((index + 1).next_power_of_two() - 1).bitxor(u32::MAX).reverse_bits();
372                 MAX_ATTR_ID.fetch_min(max_id, Ordering::Release);
373             }
374
375             Cell::new(index.reverse_bits())
376         }))
377     }
378
379     pub fn mk_attr_id(&self) -> AttrId {
380         let id = self.0.get();
381
382         // Ensure the assigned attr_id does not overlap the bits
383         // representing the number of threads.
384         #[cfg(debug_assertions)]
385         assert!(id <= MAX_ATTR_ID.load(Ordering::Acquire));
386
387         self.0.set(id + 1);
388         AttrId::from_u32(id)
389     }
390 }
391
392 pub fn mk_attr(
393     g: &AttrIdGenerator,
394     style: AttrStyle,
395     path: Path,
396     args: MacArgs,
397     span: Span,
398 ) -> Attribute {
399     mk_attr_from_item(g, AttrItem { path, args, tokens: None }, None, style, span)
400 }
401
402 pub fn mk_attr_from_item(
403     g: &AttrIdGenerator,
404     item: AttrItem,
405     tokens: Option<LazyAttrTokenStream>,
406     style: AttrStyle,
407     span: Span,
408 ) -> Attribute {
409     Attribute {
410         kind: AttrKind::Normal(P(ast::NormalAttr { item, tokens })),
411         id: g.mk_attr_id(),
412         style,
413         span,
414     }
415 }
416
417 /// Returns an inner attribute with the given value and span.
418 pub fn mk_attr_inner(g: &AttrIdGenerator, item: MetaItem) -> Attribute {
419     mk_attr(g, AttrStyle::Inner, item.path, item.kind.mac_args(item.span), item.span)
420 }
421
422 /// Returns an outer attribute with the given value and span.
423 pub fn mk_attr_outer(g: &AttrIdGenerator, item: MetaItem) -> Attribute {
424     mk_attr(g, AttrStyle::Outer, item.path, item.kind.mac_args(item.span), item.span)
425 }
426
427 pub fn mk_doc_comment(
428     g: &AttrIdGenerator,
429     comment_kind: CommentKind,
430     style: AttrStyle,
431     data: Symbol,
432     span: Span,
433 ) -> Attribute {
434     Attribute { kind: AttrKind::DocComment(comment_kind, data), id: g.mk_attr_id(), style, span }
435 }
436
437 pub fn list_contains_name(items: &[NestedMetaItem], name: Symbol) -> bool {
438     items.iter().any(|item| item.has_name(name))
439 }
440
441 impl MetaItem {
442     fn token_trees(&self) -> Vec<TokenTree> {
443         let mut idents = vec![];
444         let mut last_pos = BytePos(0_u32);
445         for (i, segment) in self.path.segments.iter().enumerate() {
446             let is_first = i == 0;
447             if !is_first {
448                 let mod_sep_span =
449                     Span::new(last_pos, segment.ident.span.lo(), segment.ident.span.ctxt(), None);
450                 idents.push(TokenTree::token_alone(token::ModSep, mod_sep_span));
451             }
452             idents.push(TokenTree::Token(Token::from_ast_ident(segment.ident), Spacing::Alone));
453             last_pos = segment.ident.span.hi();
454         }
455         idents.extend(self.kind.token_trees(self.span));
456         idents
457     }
458
459     fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItem>
460     where
461         I: Iterator<Item = TokenTree>,
462     {
463         // FIXME: Share code with `parse_path`.
464         let path = match tokens.next().map(TokenTree::uninterpolate) {
465             Some(TokenTree::Token(
466                 Token { kind: kind @ (token::Ident(..) | token::ModSep), span },
467                 _,
468             )) => 'arm: {
469                 let mut segments = if let token::Ident(name, _) = kind {
470                     if let Some(TokenTree::Token(Token { kind: token::ModSep, .. }, _)) =
471                         tokens.peek()
472                     {
473                         tokens.next();
474                         vec![PathSegment::from_ident(Ident::new(name, span))]
475                     } else {
476                         break 'arm Path::from_ident(Ident::new(name, span));
477                     }
478                 } else {
479                     vec![PathSegment::path_root(span)]
480                 };
481                 loop {
482                     if let Some(TokenTree::Token(Token { kind: token::Ident(name, _), span }, _)) =
483                         tokens.next().map(TokenTree::uninterpolate)
484                     {
485                         segments.push(PathSegment::from_ident(Ident::new(name, span)));
486                     } else {
487                         return None;
488                     }
489                     if let Some(TokenTree::Token(Token { kind: token::ModSep, .. }, _)) =
490                         tokens.peek()
491                     {
492                         tokens.next();
493                     } else {
494                         break;
495                     }
496                 }
497                 let span = span.with_hi(segments.last().unwrap().ident.span.hi());
498                 Path { span, segments, tokens: None }
499             }
500             Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. }, _)) => match *nt {
501                 token::Nonterminal::NtMeta(ref item) => return item.meta(item.path.span),
502                 token::Nonterminal::NtPath(ref path) => (**path).clone(),
503                 _ => return None,
504             },
505             _ => return None,
506         };
507         let list_closing_paren_pos = tokens.peek().map(|tt| tt.span().hi());
508         let kind = MetaItemKind::from_tokens(tokens)?;
509         let hi = match kind {
510             MetaItemKind::NameValue(ref lit) => lit.span.hi(),
511             MetaItemKind::List(..) => list_closing_paren_pos.unwrap_or(path.span.hi()),
512             _ => path.span.hi(),
513         };
514         let span = path.span.with_hi(hi);
515         Some(MetaItem { path, kind, span })
516     }
517 }
518
519 impl MetaItemKind {
520     pub fn value_str(&self) -> Option<Symbol> {
521         match self {
522             MetaItemKind::NameValue(ref v) => match v.kind {
523                 LitKind::Str(ref s, _) => Some(*s),
524                 _ => None,
525             },
526             _ => None,
527         }
528     }
529
530     pub fn mac_args(&self, span: Span) -> MacArgs {
531         match self {
532             MetaItemKind::Word => MacArgs::Empty,
533             MetaItemKind::NameValue(lit) => {
534                 let expr = P(ast::Expr {
535                     id: ast::DUMMY_NODE_ID,
536                     kind: ast::ExprKind::Lit(lit.token_lit.clone()),
537                     span: lit.span,
538                     attrs: ast::AttrVec::new(),
539                     tokens: None,
540                 });
541                 MacArgs::Eq(span, MacArgsEq::Ast(expr))
542             }
543             MetaItemKind::List(list) => {
544                 let mut tts = Vec::new();
545                 for (i, item) in list.iter().enumerate() {
546                     if i > 0 {
547                         tts.push(TokenTree::token_alone(token::Comma, span));
548                     }
549                     tts.extend(item.token_trees())
550                 }
551                 MacArgs::Delimited(
552                     DelimSpan::from_single(span),
553                     MacDelimiter::Parenthesis,
554                     TokenStream::new(tts),
555                 )
556             }
557         }
558     }
559
560     fn token_trees(&self, span: Span) -> Vec<TokenTree> {
561         match *self {
562             MetaItemKind::Word => vec![],
563             MetaItemKind::NameValue(ref lit) => {
564                 vec![
565                     TokenTree::token_alone(token::Eq, span),
566                     TokenTree::Token(lit.to_token(), Spacing::Alone),
567                 ]
568             }
569             MetaItemKind::List(ref list) => {
570                 let mut tokens = Vec::new();
571                 for (i, item) in list.iter().enumerate() {
572                     if i > 0 {
573                         tokens.push(TokenTree::token_alone(token::Comma, span));
574                     }
575                     tokens.extend(item.token_trees())
576                 }
577                 vec![TokenTree::Delimited(
578                     DelimSpan::from_single(span),
579                     Delimiter::Parenthesis,
580                     TokenStream::new(tokens),
581                 )]
582             }
583         }
584     }
585
586     fn list_from_tokens(tokens: TokenStream) -> Option<MetaItemKind> {
587         let mut tokens = tokens.into_trees().peekable();
588         let mut result = Vec::new();
589         while tokens.peek().is_some() {
590             let item = NestedMetaItem::from_tokens(&mut tokens)?;
591             result.push(item);
592             match tokens.next() {
593                 None | Some(TokenTree::Token(Token { kind: token::Comma, .. }, _)) => {}
594                 _ => return None,
595             }
596         }
597         Some(MetaItemKind::List(result))
598     }
599
600     fn name_value_from_tokens(
601         tokens: &mut impl Iterator<Item = TokenTree>,
602     ) -> Option<MetaItemKind> {
603         match tokens.next() {
604             Some(TokenTree::Delimited(_, Delimiter::Invisible, inner_tokens)) => {
605                 MetaItemKind::name_value_from_tokens(&mut inner_tokens.into_trees())
606             }
607             Some(TokenTree::Token(token, _)) => {
608                 Lit::from_token(&token).map(MetaItemKind::NameValue)
609             }
610             _ => None,
611         }
612     }
613
614     fn from_mac_args(args: &MacArgs) -> Option<MetaItemKind> {
615         match args {
616             MacArgs::Empty => Some(MetaItemKind::Word),
617             MacArgs::Delimited(_, MacDelimiter::Parenthesis, tokens) => {
618                 MetaItemKind::list_from_tokens(tokens.clone())
619             }
620             MacArgs::Delimited(..) => None,
621             MacArgs::Eq(_, MacArgsEq::Ast(expr)) => match expr.kind {
622                 ast::ExprKind::Lit(token_lit) => Some(MetaItemKind::NameValue(
623                     Lit::from_token_lit(token_lit, expr.span).expect("token_lit in from_mac_args"),
624                 )),
625                 _ => None,
626             },
627             MacArgs::Eq(_, MacArgsEq::Hir(lit)) => Some(MetaItemKind::NameValue(lit.clone())),
628         }
629     }
630
631     fn from_tokens(
632         tokens: &mut iter::Peekable<impl Iterator<Item = TokenTree>>,
633     ) -> Option<MetaItemKind> {
634         match tokens.peek() {
635             Some(TokenTree::Delimited(_, Delimiter::Parenthesis, inner_tokens)) => {
636                 let inner_tokens = inner_tokens.clone();
637                 tokens.next();
638                 MetaItemKind::list_from_tokens(inner_tokens)
639             }
640             Some(TokenTree::Delimited(..)) => None,
641             Some(TokenTree::Token(Token { kind: token::Eq, .. }, _)) => {
642                 tokens.next();
643                 MetaItemKind::name_value_from_tokens(tokens)
644             }
645             _ => Some(MetaItemKind::Word),
646         }
647     }
648 }
649
650 impl NestedMetaItem {
651     pub fn span(&self) -> Span {
652         match *self {
653             NestedMetaItem::MetaItem(ref item) => item.span,
654             NestedMetaItem::Literal(ref lit) => lit.span,
655         }
656     }
657
658     fn token_trees(&self) -> Vec<TokenTree> {
659         match *self {
660             NestedMetaItem::MetaItem(ref item) => item.token_trees(),
661             NestedMetaItem::Literal(ref lit) => {
662                 vec![TokenTree::Token(lit.to_token(), Spacing::Alone)]
663             }
664         }
665     }
666
667     fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<NestedMetaItem>
668     where
669         I: Iterator<Item = TokenTree>,
670     {
671         match tokens.peek() {
672             Some(TokenTree::Token(token, _))
673                 if let Some(lit) = Lit::from_token(token) =>
674             {
675                 tokens.next();
676                 return Some(NestedMetaItem::Literal(lit));
677             }
678             Some(TokenTree::Delimited(_, Delimiter::Invisible, inner_tokens)) => {
679                 let inner_tokens = inner_tokens.clone();
680                 tokens.next();
681                 return NestedMetaItem::from_tokens(&mut inner_tokens.into_trees().peekable());
682             }
683             _ => {}
684         }
685         MetaItem::from_tokens(tokens).map(NestedMetaItem::MetaItem)
686     }
687 }