Reputation: 1217
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'
Upvotes: 14
Views: 2550
Reputation: 3659
While the answer @mcarton gave does work perfectly fine for simple examples, it breaks a bit for more complicated ones. Rustdoc seems to insert spaces between the different doc
attributes. The markdown processor strips them out most of the time, but sometimes, it transform them to spaces instead. Consider this example:
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!");
}
This should generate the documentation "You can call this as myfoo(i32)
.", but in reality, it results in "You can call this as myfoo( i32 )
." (note the additional spaces):
I'm not too sure whether my solution would have worked with the 2017 rustc back when the question was asked, but in modern Rust, this can be done by combining 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!");
}
This results in the documentation you want (so, without superfluous spaces):
Upvotes: 10
Reputation: 30001
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:
Upvotes: 20