是否可以仅使用 `macro_rules!` 来实现这个宏?

Dog*_*ert 2 rust rust-macros

我正在尝试制作一个宏,让我遍历类型列表以减少 trait impl 样板。(我目前正在使用不同的基于宏的解决方案,但这似乎更具可读性,如果可以不添加依赖项的话。)

这是我的目标语法:

trait MyTrait {}

tfor! {
    for Ty in [i32, u32] {
        impl MyTrait for Ty {}
    }
}
Run Code Online (Sandbox Code Playgroud)

我的尝试:

macro_rules! tfor {
    (for $ty:ident in [$($typ:ident),*] $tt:tt) => {
        $(
            type $ty = $typ;
            tfor! { @extract $tt }
        )*
    };
    (@extract { $($tt:tt)* }) => {
        $($tt)*
    };
}
Run Code Online (Sandbox Code Playgroud)

这会产生错误,因为两次迭代都定义了Ty在同一范围内命名的类型:

   |
4  |               type $ty = $typ;
   |               ^^^^^^^^^^^^^^^^
   |               |
   |               `Ty` redefined here
   |               previous definition of the type `Ty` here
Run Code Online (Sandbox Code Playgroud)

操场

有没有解决的办法?我可以以某种方式生成一个随机标识符来代替,Ty以便在不使用 proc 宏或依赖项的情况下进行编译吗?

jon*_*sbb 8

您可以在const声明中确定 trait 实现的范围。这样您就可以重复使用该Ty名称而不会引起冲突。

macro_rules! tfor {
    (for $ty:ident in [$($typ:ident),*] $tt:tt) => {
        $(
            const _: () = {
                type $ty = $typ;
                tfor! { @extract $tt }
            };
        )*
    };
    (@extract { $($tt:tt)* }) => {
        $($tt)*
    };
}

trait MyTrait {}

tfor! {
    for Ty in [i32, u32] {
        impl MyTrait for Ty {}
    }
}
Run Code Online (Sandbox Code Playgroud)