在macro_rules里面匹配 - 不能使用'_'

时间:2018-03-13 05:47:05

标签: rust

我正在尝试定义宏以简化枚举的创建 可以转换为/来自str:

macro_rules! define_enum_with_str_values {
    ($Name:ident { $($Variant:ident => $StrVar:expr),* $(,)* }) => {
        #[derive(Debug, Clone, Copy, PartialEq)]
        pub enum $Name {
            $($Variant),*,
        }
        impl Into<&'static str> for $Name {
            fn into(self) -> &'static str {
                match self {
                    $($Name::$Variant => $StrVar),*
                }
            }
        }
        impl FromStr for $Name {
            type Err = BaseError;
            fn from_str(s: &str) -> Result<Self, Self::Err> {
                let obj = match s {
                    $($StrVar => $Name::$Variant),*
                };
                Ok(obj)
            }
        }
    }
}

define_enum_with_str_values!(Foo { Aa => "a", Bb => "b" });

此代码未编译,因为我没有定义'_'规则, 但如果我定义'_'规则:

    impl FromStr for $Name {
        type Err = BaseError;
        fn from_str(s: &str) -> Result<Self, Self::Err> {
            let obj = match s {
                $($StrVar => $Name::$Variant),*
                    _ => {}
            };
            Ok(obj)
        }
    }

我遇到了这样的编译错误:

error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, `}`, or an operator, found `_`
  --> foo.rs:74:25
   |
73 |                     $($StrVar => $Name::$Variant),*
   |                                                 - expected one of 8 possible tokens here
74 |                         _ => {}
   |                         ^ unexpected token
...
82 | define_enum_with_str_values!(Foo { Aa => "a", Bb => "b" });
   | ----------------------------------------------------------- in this macro invocation

1 个答案:

答案 0 :(得分:2)

考虑当展开该宏时会发生什么。有问题的match将如下所示:

let obj = match s {
    "a" => Foo::Aa , "b" => Foo::Bb
        _ => {}
};

请注意"b"_之间缺少逗号。最简单的解决方法是确保每个臂后都有一个逗号:

let obj = match s {
    $($StrVar => $Name::$Variant,)*
    _ => return Err(BaseError)
};