# ParseNestedMeta in syn::meta - Rust
Context for parsing a single property in the conventional syntax for structured attributes.

syn::meta

# Struct ParseNestedMeta

Source

    #[non_exhaustive]pub struct ParseNestedMeta<'a> {
        pub path: Path,
        pub input: ParseStream<'a>,
    }

Expand description

Context for parsing a single property in the conventional syntax for structured attributes.

## §Examples

Refer to usage examples on the following two entry-points:

- `Attribute::parse_nested_meta` if you have an entire `Attribute` to parse. Always use this if possible. Generally this is able to produce better error messages because `Attribute` holds span information for all of the delimiters therein.

- `syn::meta::parser` if you are implementing a `proc_macro_attribute` macro and parsing the arguments to the attribute macro, i.e. the ones written in the same attribute that dispatched the macro invocation. Rustc does not pass span information for the surrounding delimiters into the attribute macro invocation in this situation, so error messages might be less precise.

## Fields (Non-exhaustive)§

This struct is marked as non-exhaustive
Non-exhaustive structs could have additional fields added in future. Therefore, non-exhaustive structs cannot be constructed in external crates using the traditional `Struct { .. }` syntax; cannot be matched against without a wildcard `..`; and struct update syntax will not work.
§ `path: Path` § `input: ParseStream<'a>`

## Implementations§

Source §

### impl<'a> ParseNestedMeta<'a>

Source

#### pub fn value(&self) -> Result<ParseStream<'a>>

Used when parsing `key = "value"` syntax.

All it does is advance `meta.input` past the `=` sign in the input. You could accomplish the same effect by writing `meta.parse::<Token![=]>()?`, so at most it is a minor convenience to use `meta.value()?`.

##### §Example

    use syn::{parse_quote, Attribute, LitStr};

    let attr: Attribute = parse_quote! {
        #[tea(kind = "EarlGrey")]
    };
                                             // conceptually:
    if attr.path().is_ident("tea") {         // this parses the `tea`
        attr.parse_nested_meta(|meta| {      // this parses the `(`
            if meta.path.is_ident("kind") {  // this parses the `kind`
                let value = meta.value()?;   // this parses the `=`
                let s: LitStr = value.parse()?;  // this parses `"EarlGrey"`
                if s.value() == "EarlGrey" {
                    // ...
                }
                Ok(())
            } else {
                Err(meta.error("unsupported attribute"))
            }
        })?;
    }

Source

#### pub fn parse_nested_meta( &self, logic: impl FnMut(ParseNestedMeta<'_>) -> Result<()>, ) -> Result<()>

Used when parsing `list(...)` syntax if the content inside the nested parentheses is also expected to conform to Rust’s structured attribute convention.

##### §Example

    use syn::{parse_quote, Attribute};

    let attr: Attribute = parse_quote! {
        #[tea(with(sugar, milk))]
    };

    if attr.path().is_ident("tea") {
        attr.parse_nested_meta(|meta| {
            if meta.path.is_ident("with") {
                meta.parse_nested_meta(|meta| {  // <---
                    if meta.path.is_ident("sugar") {
                        // Here we can go even deeper if needed.
                        Ok(())
                    } else if meta.path.is_ident("milk") {
                        Ok(())
                    } else {
                        Err(meta.error("unsupported ingredient"))
                    }
                })
            } else {
                Err(meta.error("unsupported tea property"))
            }
        })?;
    }

##### §Counterexample

If you don’t need `parse_nested_meta`’s help in parsing the content written within the nested parentheses, keep in mind that you can always just parse it yourself from the exposed ParseStream. Rust syntax permits arbitrary tokens within those parentheses so for the crazier stuff, `parse_nested_meta` is not what you want.

    use syn::{parenthesized, parse_quote, Attribute, LitInt};

    let attr: Attribute = parse_quote! {
        #[repr(align(32))]
    };

    let mut align: Option<LitInt> = None;
    if attr.path().is_ident("repr") {
        attr.parse_nested_meta(|meta| {
            if meta.path.is_ident("align") {
                let content;
                parenthesized!(content in meta.input);
                align = Some(content.parse()?);
                Ok(())
            } else {
                Err(meta.error("unsupported repr"))
            }
        })?;
    }

Source

#### pub fn error(&self, msg: impl Display) -> Error

Report that the attribute’s content did not conform to expectations.

The span of the resulting error will cover `meta.path` and everything that has been parsed so far since it.

There are 2 ways you might call this. First, if `meta.path` is not something you recognize:

    attr.parse_nested_meta(|meta| {
        if meta.path.is_ident("kind") {
            // ...
            Ok(())
        } else {
            Err(meta.error("unsupported tea property"))
        }
    })?;

In this case, it behaves exactly like `syn::Error::new_spanned(&meta.path, "message...")`.

    error: unsupported tea property
     --> src/main.rs:3:26
      |
    3 | #[tea(kind = "EarlGrey", wat = "foo")]
      |                          ^^^

More usefully, the second place is if you’ve already parsed a value but have decided not to accept the value:

    use syn::Expr;

    attr.parse_nested_meta(|meta| {
        if meta.path.is_ident("kind") {
            let expr: Expr = meta.value()?.parse()?;
            match expr {
                Expr::Lit(expr) => /* ... */
                Expr::Path(expr) => /* ... */
                Expr::Macro(expr) => /* ... */
                _ => Err(meta.error("tea kind must be a string literal, path, or macro")),
            }
        } else /* as above */

    })?;

    error: tea kind must be a string literal, path, or macro
     --> src/main.rs:3:7
      |
    3 | #[tea(kind = async { replicator.await })]
      |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Often you may want to use `syn::Error::new_spanned` even in this situation. In the above code, that would be:

        match expr {
            Expr::Lit(expr) => /* ... */
            Expr::Path(expr) => /* ... */
            Expr::Macro(expr) => /* ... */
            _ => Err(Error::new_spanned(expr, "unsupported expression type for `kind`")),
        }

    error: unsupported expression type for `kind`
     --> src/main.rs:3:14
      |
    3 | #[tea(kind = async { replicator.await })]
      |              ^^^^^^^^^^^^^^^^^^^^^^^^^^

## Auto Trait Implementations§

§

### impl<'a> Freeze for ParseNestedMeta<'a>

§

### impl<'a> RefUnwindSafe for ParseNestedMeta<'a>

§

### impl<'a> !Send for ParseNestedMeta<'a>

§

### impl<'a> !Sync for ParseNestedMeta<'a>

§

### impl<'a> Unpin for ParseNestedMeta<'a>

§

### impl<'a> UnwindSafe for ParseNestedMeta<'a>

## Blanket Implementations§

Source §

### impl<T> Any for T
where T: 'static + ?Sized,

Source §

#### fn type_id(&self) -> TypeId

Gets the `TypeId` of `self`. Read more
Source §

### impl<T> Borrow<T> for T
where T: ?Sized,

Source §

#### fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source §

### impl<T> BorrowMut<T> for T
where T: ?Sized,

Source §

#### fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source §

### impl<T> From<T> for T

Source §

#### fn from(t: T) -> T

Returns the argument unchanged.

Source §

### impl<T, U> Into<U> for T
where U: From<T>,

Source §

#### fn into(self) -> U

Calls `U::from(self)`.

That is, this conversion is whatever the implementation of `From<T> for U` chooses to do.

Source §

### impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source §

#### type Error = Infallible

The type returned in the event of a conversion error.
Source §

#### fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source §

### impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source §

#### type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source §

#### fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.