Here is the code:
struct A<'a, 'b> {
s1: &'a str,
s2: &'b str,
}
struct B<'a> {
s3: &'a str,
}
macro_rules! gen_fn {
( $name:ident, $param:ty, < $($gen:tt),+ > ) => {
fn $name< $($gen),+ >(param: $param< $($gen),+ >) {
todo!()
}
}
}
fn main() {
gen_fn!( op_a, A, <'a, 'b>);
gen_fn!( op_b, B, <'a> );
}
However this code can’t compile because Rust consider $param as a single argument, and $gen is another argument, so it expect token , or ).
When I try to expand the macro, the code is generated as I expect:
fn op_a<'a, 'b>(param: A<'a, 'b>) {
$crate::panicking::panic("not yet implemented")
}
fn op_b<'a>(param: B<'a>) {
$crate::panicking::panic("not yet implemented")
}
Am I doing wrong or it is just unsupported.
>Solution :
You can use ident instead of ty, but only if you’re not using paths (a::b):
macro_rules! gen_fn {
( $name:ident, $param:ident, < $($gen:tt),+ > ) => {
fn $name< $($gen),+ >(param: $param< $($gen),+ >) {
todo!()
}
}
}
If you’re using paths, you can use a repeated ident:
macro_rules! gen_fn {
( $name:ident, $($param:ident)::+, < $($gen:tt),+ > ) => {
fn $name< $($gen),+ >(param: $($param)::+< $($gen),+ >) {
todo!()
}
}
}