如何将 Rust 宏变量嵌入到文档中?

How to embed a Rust macro variable into documentation?

我想在宏生成的文档中使用宏变量:

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

        }
    };
}

但是,变量不会被替换。我也尝试使用 #[doc] 属性:

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

        }
    };
}

这个甚至无法解析:unexpected token: 'concat'

这可以使用递归宏来完成:

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!");
}

呈现为:

虽然 对于简单的例子来说工作得很好,但对于更复杂的例子来说有点问题。 Rustdoc 似乎在不同的 doc 属性之间插入了空格。 Markdown 处理器大部分时间都会将它们剥离,但有时,它会将它们转换为空格。考虑这个例子:

macro_rules! impl_foo {
    ($name:ident, $sname:expr) => {
        #[doc = "You can call this as `myfoo("]
        #[doc = $sname]
        #[doc = ")`."]
        pub fn myfoo(_: $name) -> $name {
            42
        }
    };

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

impl_foo!(i32);


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

这应该会生成文档“您可以将其称为 myfoo(i32)”,但实际上,它会生成“您可以将其称为 myfoo( i32 )”。 (注意额外的空格):

当问题被问到时,我不太确定我的解决方案是否适用于 2017 rustc,但在现代 Rust 中,这可以通过结合 stringify! with concat!:

macro_rules! impl_foo {
    ($name:tt) => {
        #[doc = concat!("You can call this as `myfoo(", stringify!($name), ")`.")]
        pub fn myfoo(_: $name) -> $name {
            42
        }
    };
}

impl_foo!(i32);


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

这将生成您想要的文档(因此,没有多余的空格):