我试图写一个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>)
,使它工作得很好。
我如何理解编译器的抱怨,以及如何编写一个宏来生成我想要的枚举类型?
1条答案
按热度按时间1cosmwyk1#
问题是
A
通常不会是一个 complete 类型,它缺少一个泛型参数,因此要在宏中使用它,需要使用匿名生存期,即。你的宏调用相当于my_macro!(A<'_>)
。换句话说,$ty
不能像A
那样是部分应用的泛型类型,它必须是像A<'_>
那样的完整类型,因此$ty<'a>
在语义上没有任何意义,就像String<'a>
没有意义一样,String
不接受泛型生命周期参数,$ty:ty
也不能。这就是为什么你会看到错误。要修复它,您可以简单地采用最常见的令牌类型:
tt