rust 为什么serde的Serialize/Serialize派生在const _:()块中生成代码?

vsikbqxv  于 6个月前  发布在  其他
关注(0)|答案(1)|浏览(74)

注意:这个问题不是专门关于serde的:它是关于过程宏和常量函数的。
我正在研究serde的派生宏为SerializeDeserialize生成的代码,我还没有弄清楚为什么它的所有代码都在const _: ()中。
比如说,

#[derive(Deserialize)]
struct MyNewType(i32);

字符串
扩展为(使用cargo expand):

#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
    #[allow(unused_extern_crates, clippy::useless_attribute)]
    extern crate serde as _serde;
    #[automatically_derived]
    impl<'de> _serde::Deserialize<'de> for MyNewType {
        fn deserialize<__D>(
            __deserializer: __D,
        ) -> _serde::__private::Result<Self, __D::Error>
        where
            __D: _serde::Deserializer<'de>,
        {
         // generated implementation omitted for brevity
        }
    }
};


我发现,如果我仔细地复制const _: () = {...}块中的东西,并在删除#[derive(Deserialize)]标记后将其粘贴回源代码中,它似乎都可以编译,并且并行化继续正常工作。那么,将所有东西放在const _: ()块中对我的程序有什么作用呢?

v2g6jxz6

v2g6jxz61#

当你复制粘贴到你自己的作用域中时,你也复制了这一行。

#[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde;

字符串
这会在当前作用域中引入一个名为_serde的名称。如果你不知道如何查找它,这可能会与你自己的代码发生冲突。更糟糕的是,如果多个Deserialize宏在同一作用域中扩展,那么它们将引入相同的名称,这是一个问题。

const _: () = {
  ...
}


所以我们运行一个块来获得一个新的局部作用域,它不会干扰任何东西。这个块返回(),我们忽略了绑定它。我不完全确定为什么他们需要一个变量(而不仅仅是花括号),尽管我怀疑这可能是为了抑制未使用的变量警告或防止死代码消除。

相关问题