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

tor*_*eyy 7 documentation macros rust

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

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

        }
    };
}
Run Code Online (Sandbox Code Playgroud)

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

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

        }
    };
}
Run Code Online (Sandbox Code Playgroud)

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

mca*_*ton 11

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

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!");
}
Run Code Online (Sandbox Code Playgroud)

其呈现为:

来自rustdoc的例子


sk_*_*ant 9

虽然@mcarton 给出的答案对于简单的例子来说确实工作得很好,但对于更复杂的例子来说它有点破坏。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!");
}
Run Code Online (Sandbox Code Playgroud)

这应该生成文档“您可以将其称为myfoo(i32).”,但实际上,它会生成“您可以将其称为myfoo( i32 ).”。(注意额外的空格):rustdoc 页面的屏幕截图显示了额外的空格

当问题被提出时,我不太确定我的解决方案是否适用于 2017 rustc,但在现代 Rust 中,这可以通过结合来stringify!完成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!");
}
Run Code Online (Sandbox Code Playgroud)

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

修复后的 rustdoc 页面的屏幕截图