rust 在宏展开中指定了生存期的枚举变量数据类型

8xiog9wr  于 2023-05-18  发布在  其他
关注(0)|答案(1)|浏览(130)

我试图写一个Rust宏,它扩展为一个枚举,其变体包含需要生命周期注解的类型的数据,而编译器不允许。
我把这个问题归结为这个最小的例子:

struct A<'a> {
    s: &'a str
}

macro_rules! my_macro {
    ( $ty:ty ) => {
        enum E<'a> {
            M($ty<'a>)
        }
    }
}

my_macro!(A);

正如您所看到的,这意味着写出一个枚举E,其中包含一个变量M,该变量包含的数据的类型取自宏参数,并被赋予一个生命周期参数'a。但是尝试编译它会产生一堆我觉得奇怪的错误(我已经从编译器的确切输出中缩短了一点):

error: lifetime in trait object type must be followed by `+` --> src/lib.rs:8:19
   |
8  |             M($ty<'a>)
   |                   ^^
...
13 | my_macro!(A);
   | ------------ in this macro invocation
   |
   = note: this error originates in the macro `my_macro` (in Nightly builds, run with -Z macro-backtrace for more info)

error: expected one of `)` or `,`, found `<` --> src/lib.rs:8:18
   |
8  |             M($ty<'a>)
   |                  ^
   |                  expected one of `)` or `,`
   |                  help: missing `,`

error: expected one of `)`, `+`, or `,`, found `>` --> src/lib.rs:8:21
   |
8  |             M($ty<'a>)
   |                     ^ expected one of `)`, `+`, or `,`

我完全不明白什么特质对象?据我所知没有。
另外,用一个不使用宏类型变量$ty的变量定义替换M($ty<'a>),例如M(A<'a>),使它工作得很好。
我如何理解编译器的抱怨,以及如何编写一个宏来生成我想要的枚举类型?

1cosmwyk

1cosmwyk1#

问题是A通常不会是一个 complete 类型,它缺少一个泛型参数,因此要在宏中使用它,需要使用匿名生存期,即。你的宏调用相当于my_macro!(A<'_>)。换句话说,$ty不能像A那样是部分应用的泛型类型,它必须是像A<'_>那样的完整类型,因此$ty<'a>在语义上没有任何意义,就像String<'a>没有意义一样,String不接受泛型生命周期参数,$ty:ty也不能。这就是为什么你会看到错误。
要修复它,您可以简单地采用最常见的令牌类型:tt

macro_rules! my_macro {
    ( $ty:tt ) => {
        enum E<'a> {
            M($ty<'a>)
        }
    }
}

相关问题