Unexpected parsing error in attribute macro

Hi everybody.

This the example shown at GitHub - TedDriggs/darling: A Rust proc-macro attribute parser , slightly modified:

/* main.rs */
use macros_lib::your_attr;

#[your_attr(path = "hello", min = -15.0, max = 20.0)]
fn do_stuff() {
    println!("Hello");
}

and

/* lib.rs */
use darling::{Error, FromMeta};
use darling::ast::NestedMeta;
use syn::ItemFn;
use proc_macro::TokenStream;

#[derive(Debug, FromMeta)]
struct MacroArgs {
    min: f32,
    max: f32,
    path: String,
}

#[proc_macro_attribute]
pub fn your_attr(args: TokenStream, input: TokenStream) -> TokenStream {
    let attr_args = match NestedMeta::parse_meta_list(args.into()) {
        Ok(v) => v,
        Err(e) => { return TokenStream::from(Error::from(e).write_errors()); }
    };
    let _input = syn::parse_macro_input!(input as ItemFn);

    let args = match MacroArgs::from_list(&attr_args) {
        Ok(v) => v,
        Err(e) => { return TokenStream::from(e.write_errors()); }
    };

    eprintln!("ARGS: {args:#?}");

    unimplemented!()
}

compiling, I get:

error: Unexpected literal type `unary`
 --> src/main.rs:3:35
  |
3 | #[your_attr(path = "hello", min = -15.0, max = 20.0)]
  |                                   ^

If I change the min = -15.0 into a positive number, min = 15.0, it works. Googling around I found many help requests about problems parsing the - sign inside macros, so I guess I stumbled upon the same case, but I wasn't able to see any solution.

Moreover, if I remove completely the max parameter:

#[your_attr(path = "hello", min = -15.0)]

and

#[derive(Debug, FromMeta)]
struct MacroArgs {
    min: f32,
    path: String,
}

it works, even with the negative number.
How can I work around this?

Thanks.

I don't use darling crate, but just wonder if something doesn't work, why not read its documentation first?

Number

  • As a string literal, e.g. foo = "-25".
  • As an unquoted positive value, e.g. foo = 404. Negative numbers must be in quotation marks.

src: FromMeta in darling - Rust

Thank you for pointing that out to me.

I didn't go immediately to the documentation because it's quite a strange behavior: negative numbers are numbers just like the positives ones and, especially, because it's inconsistent: it isn't true that all negative number must be in quotation marks, just remove another argument and quotation marks are no longer necessary. Feels a lot like a bug, documentation isn't the first tool to work around bugs.

Anyway, next time I'll refer to the documentation. Thanks again!

1 Like