【问题标题】:What does the error `cannot be named the same as a tuple variant` mean?错误“不能与元组变量命名相同”是什么意思?
【发布时间】:2018-02-14 08:53:12
【问题描述】:

所以我正在制作一个基于simplecs的ECS。

我有一个宏,可以生成如下所示的实体结构:

($($name:ident : $component:ty,)*) => {
        /// A collection of pointers to components
        #[derive(Clone, Debug, Deserialize, PartialEq)]
        pub struct Entity {
            $(
            pub $name: Option<($component)>,
            )*
            children: Vec<Entity>
        }
}

我的目标是使用 serde 来序列化实体,但这会在组件应该存在的地方留下一堆丑陋的 None 值。所以我尝试实现一个如下所示的自定义序列化程序:

impl Serialize for Entity {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        let mut num_fields = 0;
         $(
             match self.$name {
                 Some => num_fields += 1,
                 None => {}
             };
          )*
          let mut state = serializer.serialize_struct("Entity", num_fields)?;
          // do serialize
          state.end()
    }
}

序列化程序尝试通过作为宏参数 ($name) 提供的名称访问字段,但是当我去编译它时,我得到了这个错误

error[E0530]: match bindings cannot shadow tuple variants
  |
  |         Some => {}
  |         ^^^^ cannot be named the same as a tuple variant

【问题讨论】:

  • 您使用的是Some 而不是Some(pattern)。如果您不关心内容,请在 if 条件中使用 self.$name.is_some() 而不是使用匹配项。

标签: macros rust


【解决方案1】:

语法self.$name 可以正确访问成员变量。正如@oli_obk-ker 在问题评论中所说,错误是由于使用Some 而不是Some(pattern)

         match self.$name {
             Some(_) => num_fields += 1,
//               ^~~
             None => {}
         };
//
// even better, use `if self.$name.is_some() { num_fields += 1; }`.

但是,您甚至不需要编写自己的serialize。您可以在字段上使用 #[serde(skip_serializing_if = "f") attribute,这会导致生成的代码在 f(&amp;self.field) 返回 true 时避免将其写出。

($($name:ident : $component:ty,)*) => {
    /// A collection of pointers to components
    #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
    pub struct Entity {
        $(
          #[serde(skip_serializing_if = "Option::is_none")]  // <-- add this
          pub $name: Option<($component)>,
        )*
        children: Vec<Entity>
    }
}

【讨论】:

  • 这让我对使用OkResult&lt;(), Error&gt; 感到困惑。我觉得 _ 需要 () 有点奇怪,但我很懒。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-18
  • 2012-05-22
  • 1970-01-01
  • 1970-01-01
  • 2011-03-17
  • 1970-01-01
相关资源
最近更新 更多