Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

syn::meta::parser should not fail on empty meta list #1460

Closed
nicopap opened this issue May 26, 2023 · 0 comments · Fixed by #1461
Closed

syn::meta::parser should not fail on empty meta list #1460

nicopap opened this issue May 26, 2023 · 0 comments · Fixed by #1461

Comments

@nicopap
Copy link

nicopap commented May 26, 2023

My #[proc_macro_attribute] optionally accepts config flags as a meta list. So I used syn's syn::meta::parser to read the attributes.

However, it fails when the meta list is empty, with no way of controlling this behavior.

Say I have a Config struct as follow:

#[derive(Default)]
pub(crate) struct Config {
    zoobi_whoop: Option<Ident>,
    badhi_wabbi: Option<Ident>,
    bopple_beep: Option<syn::Visibility>,
}

I have a parse method on Config as follow, similar to the one in the doc example:

        match () {
            () if meta.path.is_ident("zoobi_whoop") => {
                let value = meta.value()?;
                self.zoobi_whoop = Some(value.parse()?);
            }
            // ... parse badhi_wabbi and bopple_beep
            () => {
                return Err(meta.error("Unrecognized do_woobah meta attribute"));
            }
        }
        Ok(())

I will use syn::meta::parser as follow:

#[proc_macro_attribute]
pub fn do_woobah(attrs: TokenStream1, input: TokenStream1) -> TokenStream1 {
    let mut config = Config::default();
    let config_parser = syn::meta::parser(|meta| config.parse(meta));
    parse_macro_input!(attrs with config_parser);
    // Use `config` here
}

I can call do_woobah as follow:

#[do_woobah(zoobi_whoop = beep_bop)]
fn wobble_function() {}

However, usually, do_woobah doesn't have a meta list, the default config values are enough most of the time.

#[do_woobah]
fn wobble_function() {}

This fails to compile when using syn::meta::parser. To me, it doesn't make sense that this should fail. I don't see the interest in failing on an empty meta list.

Say you have mandatory config options. Regardless of whether the options are mandatory or not, you still need to check afterward that all mandatory config options are set, and ideally tell the user what to options are missing, so this behavior is unwishable in this case as well.

Workaround

Thankfully, TokenStream exposes a is_empty() method, and I can use it to avoid running syn::meta::parse when attrs is empty:

pub fn do_woobah(attrs: TokenStream1, input: TokenStream1) -> TokenStream1 {
    let mut config = Config::default();

    if !attrs.is_empty() {
        let config_parser = syn::meta::parser(|meta| config.parse(meta));
        parse_macro_input!(attrs with config_parser);
    }
    // Use `config` here
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant