简而言之,在Rust代码中,我试图生成一个模式匹配,如下所示:
if let Foo::Variant(_) = value {}
// ^^^^^^^^^^^^^^^
在宏中,同时将Foo
(一种类型)和Variant
(一种标识符)作为元变量传递给宏。在实际的用例中,我生成的是match
而不是if let
,并且正在使用同一枚举的多个变体,但是if let
导致了一个较短的可重现示例。这适用于简单的枚举:
enum Foo {
Variant,
}
macro_rules! match_enum {
(
$value:ident: <$enum:ty>::$variant:ident
) => {
if let <$enum>::$variant = $value {}
};
}
fn main() {
let foo = Foo::Variant;
match_enum!(foo: <Foo>::Variant);
}
这样编译。但是,当我使枚举变量类似于元组时,它会中断(更改突出显示):
enum Foo {
Variant(usize),
// ^^^^^^^
}
macro_rules! match_enum {
(
$value:ident: <$enum:ty>::$variant:ident
) => {
if let <$enum>::$variant(_) = $value {}
// ^^^
};
}
fn main() {
let foo = Foo::Variant(0);
// ^^^
match_enum!(foo: <Foo>::Variant);
}
| if let <$enum>::$variant(_) = $value {}
| -----------------^^^ unexpected `(` after qualified path
| |
| the qualified path
...
| match_enum!(foo: <Foo>::Variant);
| --------------------------------- in this macro invocation
我或多或少地尝试了一些变化;其中的$enum::$variant(_)
,<$enum::$variant>(_)
,<$enum::$variant>::(_)
。这可能吗?我可能使用了错误类型的元变量吗?
This question似乎相关,但是它专注于混合单元和元组变体,尚未解决。
最佳答案
该问题似乎是由$enum
元变量引起的,如以下所示:
macro_rules! match_enum {
(
$value:ident: <$enum:ty>::$variant:ident
) => {
// does not fix the problem
if let <$enum>::Variant(_) = $value {}
// fixes the problem
if let Bar::$variant(_) = $value {}
};
}
当问题发生在语法级别时,我们可以尝试更改所生成代码的语法结构,特别是通过引入类型别名。然后,我们需要限制该类型的范围,以免泄漏出宏:macro_rules! match_enum {
(
$value:ident: <$enum:ty>::$variant:ident
) => {
{
type Enum = $enum;
if let Enum::Variant(_) = $value {}
}
};
}
这只是一种解决方法,但足够干净。
关于enums - 在宏中匹配类似元组的枚举变量,其中枚举类型和变量是元变量: how do I write the matching pattern?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64146439/