1 use super::*;
2 use crate::punctuated::Punctuated;
3 
4 use std::iter;
5 
6 use proc_macro2::TokenStream;
7 
8 #[cfg(feature = "parsing")]
9 use crate::parse::{Parse, ParseBuffer, ParseStream, Parser, Result};
10 #[cfg(feature = "parsing")]
11 use crate::punctuated::Pair;
12 #[cfg(feature = "extra-traits")]
13 use crate::tt::TokenStreamHelper;
14 #[cfg(feature = "extra-traits")]
15 use std::hash::{Hash, Hasher};
16 
17 ast_struct! {
18     /// An attribute like `#[repr(transparent)]`.
19     ///
20     /// *This type is available only if Syn is built with the `"derive"` or `"full"`
21     /// feature.*
22     ///
23     /// <br>
24     ///
25     /// # Syntax
26     ///
27     /// Rust has six types of attributes.
28     ///
29     /// - Outer attributes like `#[repr(transparent)]`. These appear outside or
30     ///   in front of the item they describe.
31     /// - Inner attributes like `#![feature(proc_macro)]`. These appear inside
32     ///   of the item they describe, usually a module.
33     /// - Outer doc comments like `/// # Example`.
34     /// - Inner doc comments like `//! Please file an issue`.
35     /// - Outer block comments `/** # Example */`.
36     /// - Inner block comments `/*! Please file an issue */`.
37     ///
38     /// The `style` field of type `AttrStyle` distinguishes whether an attribute
39     /// is outer or inner. Doc comments and block comments are promoted to
40     /// attributes, as this is how they are processed by the compiler and by
41     /// `macro_rules!` macros.
42     ///
43     /// The `path` field gives the possibly colon-delimited path against which
44     /// the attribute is resolved. It is equal to `"doc"` for desugared doc
45     /// comments. The `tokens` field contains the rest of the attribute body as
46     /// tokens.
47     ///
48     /// ```text
49     /// #[derive(Copy)]      #[crate::precondition x < 5]
50     ///   ^^^^^^~~~~~~         ^^^^^^^^^^^^^^^^^^^ ~~~~~
51     ///   path  tokens                 path        tokens
52     /// ```
53     ///
54     /// <br>
55     ///
56     /// # Parsing from tokens to Attribute
57     ///
58     /// This type does not implement the [`Parse`] trait and thus cannot be
59     /// parsed directly by [`ParseStream::parse`]. Instead use
60     /// [`ParseStream::call`] with one of the two parser functions
61     /// [`Attribute::parse_outer`] or [`Attribute::parse_inner`] depending on
62     /// which you intend to parse.
63     ///
64     /// [`Parse`]: parse::Parse
65     /// [`ParseStream::parse`]: parse::ParseBuffer::parse
66     /// [`ParseStream::call`]: parse::ParseBuffer::call
67     ///
68     /// ```
69     /// use syn::{Attribute, Ident, Result, Token};
70     /// use syn::parse::{Parse, ParseStream};
71     ///
72     /// // Parses a unit struct with attributes.
73     /// //
74     /// //     #[path = "s.tmpl"]
75     /// //     struct S;
76     /// struct UnitStruct {
77     ///     attrs: Vec<Attribute>,
78     ///     struct_token: Token![struct],
79     ///     name: Ident,
80     ///     semi_token: Token![;],
81     /// }
82     ///
83     /// impl Parse for UnitStruct {
84     ///     fn parse(input: ParseStream) -> Result<Self> {
85     ///         Ok(UnitStruct {
86     ///             attrs: input.call(Attribute::parse_outer)?,
87     ///             struct_token: input.parse()?,
88     ///             name: input.parse()?,
89     ///             semi_token: input.parse()?,
90     ///         })
91     ///     }
92     /// }
93     /// ```
94     ///
95     /// <p><br></p>
96     ///
97     /// # Parsing from Attribute to structured arguments
98     ///
99     /// The grammar of attributes in Rust is very flexible, which makes the
100     /// syntax tree not that useful on its own. In particular, arguments of the
101     /// attribute are held in an arbitrary `tokens: TokenStream`. Macros are
102     /// expected to check the `path` of the attribute, decide whether they
103     /// recognize it, and then parse the remaining tokens according to whatever
104     /// grammar they wish to require for that kind of attribute.
105     ///
106     /// If the attribute you are parsing is expected to conform to the
107     /// conventional structured form of attribute, use [`parse_meta()`] to
108     /// obtain that structured representation. If the attribute follows some
109     /// other grammar of its own, use [`parse_args()`] to parse that into the
110     /// expected data structure.
111     ///
112     /// [`parse_meta()`]: Attribute::parse_meta
113     /// [`parse_args()`]: Attribute::parse_args
114     ///
115     /// <p><br></p>
116     ///
117     /// # Doc comments
118     ///
119     /// The compiler transforms doc comments, such as `/// comment` and `/*!
120     /// comment */`, into attributes before macros are expanded. Each comment is
121     /// expanded into an attribute of the form `#[doc = r"comment"]`.
122     ///
123     /// As an example, the following `mod` items are expanded identically:
124     ///
125     /// ```
126     /// # use syn::{ItemMod, parse_quote};
127     /// let doc: ItemMod = parse_quote! {
128     ///     /// Single line doc comments
129     ///     /// We write so many!
130     ///     /**
131     ///      * Multi-line comments...
132     ///      * May span many lines
133     ///      */
134     ///     mod example {
135     ///         //! Of course, they can be inner too
136     ///         /*! And fit in a single line */
137     ///     }
138     /// };
139     /// let attr: ItemMod = parse_quote! {
140     ///     #[doc = r" Single line doc comments"]
141     ///     #[doc = r" We write so many!"]
142     ///     #[doc = r" Multi-line comments...
143     ///  May span many lines"]
144     ///     mod example {
145     ///         #![doc = r" Of course, they can be inner too"]
146     ///         #![doc = r" And fit in a single line "]
147     ///     }
148     /// };
149     /// assert_eq!(doc, attr);
150     /// ```
151     pub struct Attribute #manual_extra_traits {
152         pub pound_token: Token![#],
153         pub style: AttrStyle,
154         pub bracket_token: token::Bracket,
155         pub path: Path,
156         pub tokens: TokenStream,
157     }
158 }
159 
160 #[cfg(feature = "extra-traits")]
161 impl Eq for Attribute {}
162 
163 #[cfg(feature = "extra-traits")]
164 impl PartialEq for Attribute {
eq(&self, other: &Self) -> bool165     fn eq(&self, other: &Self) -> bool {
166         self.style == other.style
167             && self.pound_token == other.pound_token
168             && self.bracket_token == other.bracket_token
169             && self.path == other.path
170             && TokenStreamHelper(&self.tokens) == TokenStreamHelper(&other.tokens)
171     }
172 }
173 
174 #[cfg(feature = "extra-traits")]
175 impl Hash for Attribute {
hash<H>(&self, state: &mut H) where H: Hasher,176     fn hash<H>(&self, state: &mut H)
177     where
178         H: Hasher,
179     {
180         self.style.hash(state);
181         self.pound_token.hash(state);
182         self.bracket_token.hash(state);
183         self.path.hash(state);
184         TokenStreamHelper(&self.tokens).hash(state);
185     }
186 }
187 
188 impl Attribute {
189     /// Parses the content of the attribute, consisting of the path and tokens,
190     /// as a [`Meta`] if possible.
191     ///
192     /// *This function is available only if Syn is built with the `"parsing"`
193     /// feature.*
194     #[cfg(feature = "parsing")]
parse_meta(&self) -> Result<Meta>195     pub fn parse_meta(&self) -> Result<Meta> {
196         fn clone_ident_segment(segment: &PathSegment) -> PathSegment {
197             PathSegment {
198                 ident: segment.ident.clone(),
199                 arguments: PathArguments::None,
200             }
201         }
202 
203         let path = Path {
204             leading_colon: self
205                 .path
206                 .leading_colon
207                 .as_ref()
208                 .map(|colon| Token![::](colon.spans)),
209             segments: self
210                 .path
211                 .segments
212                 .pairs()
213                 .map(|pair| match pair {
214                     Pair::Punctuated(seg, punct) => {
215                         Pair::Punctuated(clone_ident_segment(seg), Token![::](punct.spans))
216                     }
217                     Pair::End(seg) => Pair::End(clone_ident_segment(seg)),
218                 })
219                 .collect(),
220         };
221 
222         let parser = |input: ParseStream| parsing::parse_meta_after_path(path, input);
223         parse::Parser::parse2(parser, self.tokens.clone())
224     }
225 
226     /// Parse the arguments to the attribute as a syntax tree.
227     ///
228     /// This is similar to `syn::parse2::<T>(attr.tokens)` except that:
229     ///
230     /// - the surrounding delimiters are *not* included in the input to the
231     ///   parser; and
232     /// - the error message has a more useful span when `tokens` is empty.
233     ///
234     /// ```text
235     /// #[my_attr(value < 5)]
236     ///           ^^^^^^^^^ what gets parsed
237     /// ```
238     ///
239     /// *This function is available only if Syn is built with the `"parsing"`
240     /// feature.*
241     #[cfg(feature = "parsing")]
parse_args<T: Parse>(&self) -> Result<T>242     pub fn parse_args<T: Parse>(&self) -> Result<T> {
243         self.parse_args_with(T::parse)
244     }
245 
246     /// Parse the arguments to the attribute using the given parser.
247     ///
248     /// *This function is available only if Syn is built with the `"parsing"`
249     /// feature.*
250     #[cfg(feature = "parsing")]
parse_args_with<F: Parser>(&self, parser: F) -> Result<F::Output>251     pub fn parse_args_with<F: Parser>(&self, parser: F) -> Result<F::Output> {
252         let parser = |input: ParseStream| {
253             let args = enter_args(self, input)?;
254             parse::parse_stream(parser, &args)
255         };
256         parser.parse2(self.tokens.clone())
257     }
258 
259     /// Parses zero or more outer attributes from the stream.
260     ///
261     /// *This function is available only if Syn is built with the `"parsing"`
262     /// feature.*
263     #[cfg(feature = "parsing")]
parse_outer(input: ParseStream) -> Result<Vec<Self>>264     pub fn parse_outer(input: ParseStream) -> Result<Vec<Self>> {
265         let mut attrs = Vec::new();
266         while input.peek(Token![#]) {
267             attrs.push(input.call(parsing::single_parse_outer)?);
268         }
269         Ok(attrs)
270     }
271 
272     /// Parses zero or more inner attributes from the stream.
273     ///
274     /// *This function is available only if Syn is built with the `"parsing"`
275     /// feature.*
276     #[cfg(feature = "parsing")]
parse_inner(input: ParseStream) -> Result<Vec<Self>>277     pub fn parse_inner(input: ParseStream) -> Result<Vec<Self>> {
278         let mut attrs = Vec::new();
279         while input.peek(Token![#]) && input.peek2(Token![!]) {
280             attrs.push(input.call(parsing::single_parse_inner)?);
281         }
282         Ok(attrs)
283     }
284 }
285 
286 #[cfg(feature = "parsing")]
expected_parentheses(attr: &Attribute) -> String287 fn expected_parentheses(attr: &Attribute) -> String {
288     let style = match attr.style {
289         AttrStyle::Outer => "#",
290         AttrStyle::Inner(_) => "#!",
291     };
292 
293     let mut path = String::new();
294     for segment in &attr.path.segments {
295         if !path.is_empty() || attr.path.leading_colon.is_some() {
296             path += "::";
297         }
298         path += &segment.ident.to_string();
299     }
300 
301     format!("{}[{}(...)]", style, path)
302 }
303 
304 #[cfg(feature = "parsing")]
enter_args<'a>(attr: &Attribute, input: ParseStream<'a>) -> Result<ParseBuffer<'a>>305 fn enter_args<'a>(attr: &Attribute, input: ParseStream<'a>) -> Result<ParseBuffer<'a>> {
306     if input.is_empty() {
307         let expected = expected_parentheses(attr);
308         let msg = format!("expected attribute arguments in parentheses: {}", expected);
309         return Err(crate::error::new2(
310             attr.pound_token.span,
311             attr.bracket_token.span,
312             msg,
313         ));
314     } else if input.peek(Token![=]) {
315         let expected = expected_parentheses(attr);
316         let msg = format!("expected parentheses: {}", expected);
317         return Err(input.error(msg));
318     };
319 
320     let content;
321     if input.peek(token::Paren) {
322         parenthesized!(content in input);
323     } else if input.peek(token::Bracket) {
324         bracketed!(content in input);
325     } else if input.peek(token::Brace) {
326         braced!(content in input);
327     } else {
328         return Err(input.error("unexpected token in attribute arguments"));
329     }
330 
331     if input.is_empty() {
332         Ok(content)
333     } else {
334         Err(input.error("unexpected token in attribute arguments"))
335     }
336 }
337 
338 ast_enum! {
339     /// Distinguishes between attributes that decorate an item and attributes
340     /// that are contained within an item.
341     ///
342     /// *This type is available only if Syn is built with the `"derive"` or `"full"`
343     /// feature.*
344     ///
345     /// # Outer attributes
346     ///
347     /// - `#[repr(transparent)]`
348     /// - `/// # Example`
349     /// - `/** Please file an issue */`
350     ///
351     /// # Inner attributes
352     ///
353     /// - `#![feature(proc_macro)]`
354     /// - `//! # Example`
355     /// - `/*! Please file an issue */`
356     #[cfg_attr(feature = "clone-impls", derive(Copy))]
357     pub enum AttrStyle {
358         Outer,
359         Inner(Token![!]),
360     }
361 }
362 
363 ast_enum_of_structs! {
364     /// Content of a compile-time structured attribute.
365     ///
366     /// *This type is available only if Syn is built with the `"derive"` or `"full"`
367     /// feature.*
368     ///
369     /// ## Path
370     ///
371     /// A meta path is like the `test` in `#[test]`.
372     ///
373     /// ## List
374     ///
375     /// A meta list is like the `derive(Copy)` in `#[derive(Copy)]`.
376     ///
377     /// ## NameValue
378     ///
379     /// A name-value meta is like the `path = "..."` in `#[path =
380     /// "sys/windows.rs"]`.
381     ///
382     /// # Syntax tree enum
383     ///
384     /// This type is a [syntax tree enum].
385     ///
386     /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
387     //
388     // TODO: change syntax-tree-enum link to an intra rustdoc link, currently
389     // blocked on https://github.com/rust-lang/rust/issues/62833
390     pub enum Meta {
391         Path(Path),
392 
393         /// A structured list within an attribute, like `derive(Copy, Clone)`.
394         List(MetaList),
395 
396         /// A name-value pair within an attribute, like `feature = "nightly"`.
397         NameValue(MetaNameValue),
398     }
399 }
400 
401 ast_struct! {
402     /// A structured list within an attribute, like `derive(Copy, Clone)`.
403     ///
404     /// *This type is available only if Syn is built with the `"derive"` or
405     /// `"full"` feature.*
406     pub struct MetaList {
407         pub path: Path,
408         pub paren_token: token::Paren,
409         pub nested: Punctuated<NestedMeta, Token![,]>,
410     }
411 }
412 
413 ast_struct! {
414     /// A name-value pair within an attribute, like `feature = "nightly"`.
415     ///
416     /// *This type is available only if Syn is built with the `"derive"` or
417     /// `"full"` feature.*
418     pub struct MetaNameValue {
419         pub path: Path,
420         pub eq_token: Token![=],
421         pub lit: Lit,
422     }
423 }
424 
425 impl Meta {
426     /// Returns the identifier that begins this structured meta item.
427     ///
428     /// For example this would return the `test` in `#[test]`, the `derive` in
429     /// `#[derive(Copy)]`, and the `path` in `#[path = "sys/windows.rs"]`.
path(&self) -> &Path430     pub fn path(&self) -> &Path {
431         match self {
432             Meta::Path(path) => path,
433             Meta::List(meta) => &meta.path,
434             Meta::NameValue(meta) => &meta.path,
435         }
436     }
437 }
438 
439 ast_enum_of_structs! {
440     /// Element of a compile-time attribute list.
441     ///
442     /// *This type is available only if Syn is built with the `"derive"` or `"full"`
443     /// feature.*
444     pub enum NestedMeta {
445         /// A structured meta item, like the `Copy` in `#[derive(Copy)]` which
446         /// would be a nested `Meta::Path`.
447         Meta(Meta),
448 
449         /// A Rust literal, like the `"new_name"` in `#[rename("new_name")]`.
450         Lit(Lit),
451     }
452 }
453 
454 /// Conventional argument type associated with an invocation of an attribute
455 /// macro.
456 ///
457 /// For example if we are developing an attribute macro that is intended to be
458 /// invoked on function items as follows:
459 ///
460 /// ```
461 /// # const IGNORE: &str = stringify! {
462 /// #[my_attribute(path = "/v1/refresh")]
463 /// # };
464 /// pub fn refresh() {
465 ///     /* ... */
466 /// }
467 /// ```
468 ///
469 /// The implementation of this macro would want to parse its attribute arguments
470 /// as type `AttributeArgs`.
471 ///
472 /// ```
473 /// # extern crate proc_macro;
474 /// #
475 /// use proc_macro::TokenStream;
476 /// use syn::{parse_macro_input, AttributeArgs, ItemFn};
477 ///
478 /// # const IGNORE: &str = stringify! {
479 /// #[proc_macro_attribute]
480 /// # };
481 /// pub fn my_attribute(args: TokenStream, input: TokenStream) -> TokenStream {
482 ///     let args = parse_macro_input!(args as AttributeArgs);
483 ///     let input = parse_macro_input!(input as ItemFn);
484 ///
485 ///     /* ... */
486 /// #   "".parse().unwrap()
487 /// }
488 /// ```
489 pub type AttributeArgs = Vec<NestedMeta>;
490 
491 pub trait FilterAttrs<'a> {
492     type Ret: Iterator<Item = &'a Attribute>;
493 
outer(self) -> Self::Ret494     fn outer(self) -> Self::Ret;
inner(self) -> Self::Ret495     fn inner(self) -> Self::Ret;
496 }
497 
498 impl<'a, T> FilterAttrs<'a> for T
499 where
500     T: IntoIterator<Item = &'a Attribute>,
501 {
502     type Ret = iter::Filter<T::IntoIter, fn(&&Attribute) -> bool>;
503 
outer(self) -> Self::Ret504     fn outer(self) -> Self::Ret {
505         fn is_outer(attr: &&Attribute) -> bool {
506             match attr.style {
507                 AttrStyle::Outer => true,
508                 AttrStyle::Inner(_) => false,
509             }
510         }
511         self.into_iter().filter(is_outer)
512     }
513 
inner(self) -> Self::Ret514     fn inner(self) -> Self::Ret {
515         fn is_inner(attr: &&Attribute) -> bool {
516             match attr.style {
517                 AttrStyle::Inner(_) => true,
518                 AttrStyle::Outer => false,
519             }
520         }
521         self.into_iter().filter(is_inner)
522     }
523 }
524 
525 #[cfg(feature = "parsing")]
526 pub mod parsing {
527     use super::*;
528 
529     use crate::ext::IdentExt;
530     use crate::parse::{Parse, ParseStream, Result};
531     #[cfg(feature = "full")]
532     use crate::private;
533 
single_parse_inner(input: ParseStream) -> Result<Attribute>534     pub fn single_parse_inner(input: ParseStream) -> Result<Attribute> {
535         let content;
536         Ok(Attribute {
537             pound_token: input.parse()?,
538             style: AttrStyle::Inner(input.parse()?),
539             bracket_token: bracketed!(content in input),
540             path: content.call(Path::parse_mod_style)?,
541             tokens: content.parse()?,
542         })
543     }
544 
single_parse_outer(input: ParseStream) -> Result<Attribute>545     pub fn single_parse_outer(input: ParseStream) -> Result<Attribute> {
546         let content;
547         Ok(Attribute {
548             pound_token: input.parse()?,
549             style: AttrStyle::Outer,
550             bracket_token: bracketed!(content in input),
551             path: content.call(Path::parse_mod_style)?,
552             tokens: content.parse()?,
553         })
554     }
555 
556     #[cfg(feature = "full")]
557     impl private {
attrs(outer: Vec<Attribute>, inner: Vec<Attribute>) -> Vec<Attribute>558         pub fn attrs(outer: Vec<Attribute>, inner: Vec<Attribute>) -> Vec<Attribute> {
559             let mut attrs = outer;
560             attrs.extend(inner);
561             attrs
562         }
563     }
564 
565     // Like Path::parse_mod_style but accepts keywords in the path.
parse_meta_path(input: ParseStream) -> Result<Path>566     fn parse_meta_path(input: ParseStream) -> Result<Path> {
567         Ok(Path {
568             leading_colon: input.parse()?,
569             segments: {
570                 let mut segments = Punctuated::new();
571                 while input.peek(Ident::peek_any) {
572                     let ident = Ident::parse_any(input)?;
573                     segments.push_value(PathSegment::from(ident));
574                     if !input.peek(Token![::]) {
575                         break;
576                     }
577                     let punct = input.parse()?;
578                     segments.push_punct(punct);
579                 }
580                 if segments.is_empty() {
581                     return Err(input.error("expected path"));
582                 } else if segments.trailing_punct() {
583                     return Err(input.error("expected path segment"));
584                 }
585                 segments
586             },
587         })
588     }
589 
590     impl Parse for Meta {
parse(input: ParseStream) -> Result<Self>591         fn parse(input: ParseStream) -> Result<Self> {
592             let path = input.call(parse_meta_path)?;
593             parse_meta_after_path(path, input)
594         }
595     }
596 
597     impl Parse for MetaList {
parse(input: ParseStream) -> Result<Self>598         fn parse(input: ParseStream) -> Result<Self> {
599             let path = input.call(parse_meta_path)?;
600             parse_meta_list_after_path(path, input)
601         }
602     }
603 
604     impl Parse for MetaNameValue {
parse(input: ParseStream) -> Result<Self>605         fn parse(input: ParseStream) -> Result<Self> {
606             let path = input.call(parse_meta_path)?;
607             parse_meta_name_value_after_path(path, input)
608         }
609     }
610 
611     impl Parse for NestedMeta {
parse(input: ParseStream) -> Result<Self>612         fn parse(input: ParseStream) -> Result<Self> {
613             if input.peek(Lit) && !(input.peek(LitBool) && input.peek2(Token![=])) {
614                 input.parse().map(NestedMeta::Lit)
615             } else if input.peek(Ident::peek_any) {
616                 input.parse().map(NestedMeta::Meta)
617             } else {
618                 Err(input.error("expected identifier or literal"))
619             }
620         }
621     }
622 
parse_meta_after_path(path: Path, input: ParseStream) -> Result<Meta>623     pub fn parse_meta_after_path(path: Path, input: ParseStream) -> Result<Meta> {
624         if input.peek(token::Paren) {
625             parse_meta_list_after_path(path, input).map(Meta::List)
626         } else if input.peek(Token![=]) {
627             parse_meta_name_value_after_path(path, input).map(Meta::NameValue)
628         } else {
629             Ok(Meta::Path(path))
630         }
631     }
632 
parse_meta_list_after_path(path: Path, input: ParseStream) -> Result<MetaList>633     fn parse_meta_list_after_path(path: Path, input: ParseStream) -> Result<MetaList> {
634         let content;
635         Ok(MetaList {
636             path,
637             paren_token: parenthesized!(content in input),
638             nested: content.parse_terminated(NestedMeta::parse)?,
639         })
640     }
641 
parse_meta_name_value_after_path(path: Path, input: ParseStream) -> Result<MetaNameValue>642     fn parse_meta_name_value_after_path(path: Path, input: ParseStream) -> Result<MetaNameValue> {
643         Ok(MetaNameValue {
644             path,
645             eq_token: input.parse()?,
646             lit: input.parse()?,
647         })
648     }
649 }
650 
651 #[cfg(feature = "printing")]
652 mod printing {
653     use super::*;
654     use proc_macro2::TokenStream;
655     use quote::ToTokens;
656 
657     impl ToTokens for Attribute {
to_tokens(&self, tokens: &mut TokenStream)658         fn to_tokens(&self, tokens: &mut TokenStream) {
659             self.pound_token.to_tokens(tokens);
660             if let AttrStyle::Inner(b) = &self.style {
661                 b.to_tokens(tokens);
662             }
663             self.bracket_token.surround(tokens, |tokens| {
664                 self.path.to_tokens(tokens);
665                 self.tokens.to_tokens(tokens);
666             });
667         }
668     }
669 
670     impl ToTokens for MetaList {
to_tokens(&self, tokens: &mut TokenStream)671         fn to_tokens(&self, tokens: &mut TokenStream) {
672             self.path.to_tokens(tokens);
673             self.paren_token.surround(tokens, |tokens| {
674                 self.nested.to_tokens(tokens);
675             })
676         }
677     }
678 
679     impl ToTokens for MetaNameValue {
to_tokens(&self, tokens: &mut TokenStream)680         fn to_tokens(&self, tokens: &mut TokenStream) {
681             self.path.to_tokens(tokens);
682             self.eq_token.to_tokens(tokens);
683             self.lit.to_tokens(tokens);
684         }
685     }
686 }
687