注意:这个问题不是专门关于serde
的:它是关于过程宏和常量函数的。
我正在研究serde的派生宏为Serialize
和Deserialize
生成的代码,我还没有弄清楚为什么它的所有代码都在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 _: ()
块中对我的程序有什么作用呢?
1条答案
按热度按时间v2g6jxz61#
当你复制粘贴到你自己的作用域中时,你也复制了这一行。
字符串
这会在当前作用域中引入一个名为
_serde
的名称。如果你不知道如何查找它,这可能会与你自己的代码发生冲突。更糟糕的是,如果多个Deserialize
宏在同一作用域中扩展,那么它们将引入相同的名称,这是一个问题。型
所以我们运行一个块来获得一个新的局部作用域,它不会干扰任何东西。这个块返回
()
,我们忽略了绑定它。我不完全确定为什么他们需要一个变量(而不仅仅是花括号),尽管我怀疑这可能是为了抑制未使用的变量警告或防止死代码消除。