dtolnay / paste

Macros for all your token pasting needs
Apache License 2.0
1.02k stars 56 forks source link

macro expansion fails with formating types inside a string literal #68

Closed Xephobia closed 3 years ago

Xephobia commented 3 years ago

regarding this code :

use paste::paste;
use serenity::{
    framework::standard::{macros::command, CommandResult},
    model::prelude::*,
    prelude::*,
};

macro_rules! gen_random_funs {
    [$($x:ty),*] => {
        paste! {
        $(
            #[command("`"$x"`")]
            #[description = "generates a random `" $x "`"]
            async fn [<_ $x>](ctx: &Context, msg: &Message) -> CommandResult {
                msg.reply(ctx, rand::random::<$x>()).await?;
                Ok(())
            }

        )*
    }
    };
}

gen_random_funs![u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, f32, f64];

this fails with all the argument, quote unexpected token, note that macro also fail to expand in attributes in paste! blocks, this prevents the use of stringify! and such.

Xephobia commented 3 years ago

The #[command(""$x"")] bit fails because it put space around the expr, I don't know if it is really the issue, but it is unintended

dtolnay commented 3 years ago

You could do it like this:

macro_rules! gen_random_funs {
    ($($x:ty),*) => {
        $(
            paste!(gen_random_funs! {
                #[command = "" $x]
                #[description = "generates a random `" $x "`"]
                async fn [<_ $x>](ctx: &Context, msg: &Message) -> CommandResult {
                    msg.reply(ctx, rand::random::<$x>()).await?;
                    Ok(())
                }
            });
        )*
    };
    (#[command = $command:literal] $fn:item) => {
        #[command($command)]
        $fn
    };
}
Xephobia commented 3 years ago

This works, thanks! We should leave the issue open until there is a fix for the og code.

dtolnay commented 3 years ago

I think there doesn't need to be any change made in paste. #[attr("..." $x "...")] is already a syntactically valid attribute so it doesn't make sense for paste to mess with it. #[attr = "..." $x "..."] is syntactically invalid so that's the signal for paste to apply the concatenation of the strings into a single literal.