9
votes

I'd like to use a macro variable in the macro-generated documentation:

macro_rules! impl_foo {
    ($name:ident) => {
        /// Returns a new `$name`.
        fn myfoo() -> $name {

        }
    };
}

However, the variable won't be substituted. I also tried using the #[doc] attribute:

macro_rules! impl_foo {
    ($name:ident) => {
        #[doc = concat!("Returns a new `", $name, "`.")]
        fn myfoo() -> $name {

        }
    };
}

This one even fails to parse: unexpected token: 'concat'

1
@Shepmaster I couldn't find it, but I wonder why the second one fails to parse. - torkleyy
The set of allowed tokens inside an attribute is probably pretty limited. - Shepmaster
@torkleyy Macros are not expanded when parsing (which is why there is RFC 1628 "Eager expansion of macros") - kennytm
@Shepmaster I though procedural macros allowed any token in attributes now (but the #[doc] attribute itself won't know what to do with those). - mcarton

1 Answers

16
votes

This can be done using a recursive macro:

macro_rules! impl_foo {
    ($name:ident, $sname:expr) => {
        #[doc = "Returns a new `"]
        #[doc = $sname]
        #[doc = "`."]
        pub fn myfoo() -> $name {
            42
        }
    };

    ($name:tt) => {
        impl_foo!($name, stringify!($name));
    };
}

impl_foo!(u32);


fn main() {
    println!("Hello, world!");
}

Which renders as:

Example from rustdoc