错误“无法命名为元组变量”意味着什么?

the*_*ode 2 macros rust

因此,我正在基于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>
        }
}
Run Code Online (Sandbox Code Playgroud)

我的目标是使用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()
    }
}
Run Code Online (Sandbox Code Playgroud)

序列化程序尝试通过作为宏参数($name)提供的名称访问字段,但是当我进行编译时,出现此错误

error[E0530]: match bindings cannot shadow tuple variants
  |
  |         Some => {}
  |         ^^^^ cannot be named the same as a tuple variant
Run Code Online (Sandbox Code Playgroud)

ken*_*ytm 5

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; }`.
Run Code Online (Sandbox Code Playgroud)

但是,您甚至不需要编写自己的serialize。您可以在#[serde(skip_serializing_if = "f")字段上使用该属性,这会导致生成的代码避免在f(&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>
    }
}
Run Code Online (Sandbox Code Playgroud)