为什么 Serde 默认不支持 Rc 和 Arc 类型?

Why does Serde not support Rc and Arc types by default?

请解释 Serde rc 功能

Opt into impls for Rc<T> and Arc<T>. Serializing and deserializing these types does not preserve identity and may result in multiple copies of the same data. Be sure that this is what you want before enabling this feature.

Serializing a data structure containing reference-counted pointers will serialize a copy of the inner value of the pointer each time a pointer is referenced within the data structure. Serialization will not attempt to deduplicate these repeated data.

Deserializing a data structure containing reference-counted pointers will not attempt to deduplicate references to the same data. Every deserialized pointer will end up with a strong count of 1.

为什么存在这个功能标志,为什么它不是默认行为?

是什么意思

Serializing and deserializing these types does not preserve identity and may result in multiple copies of the same data

我知道它与 Serde issue 194. The last message of the issue 说有关

If you want to make sure you don't accidentally end up with a derived impl containing an rc, open a clippy issue.

是否存在功能标志以捕获 Rc 结构的意外使用?

Serde issue 194所述,反序列化到RcArc的缺点是:

  • Potentially increased memory usage
  • Equality comparison that relies on comparison of address breaks
  • Interior mutability is not reflected in copies

这在 feature flag documentation 中得到回应:

Serialization will not attempt to deduplicate these repeated data.

Deserializing a data structure containing reference-counted pointers will not attempt to deduplicate references to the same data.

RcArc 的通常目的是 共享 数据。当反序列化为包含 RcArc 的结构时,不会发生这种共享。在此示例中,创建了 5 个完全不同的 Rc<str>,尽管它们都具有相同的内容:

use std::{rc::Rc, ptr};

fn main() {
    let json = r#"[
        "alpha",
        "alpha",
        "alpha",
        "alpha",
        "alpha"
    ]"#;

    let strings = serde_json::from_str::<Vec<Rc<str>>>(json).unwrap();
    
    dbg!(ptr::eq(strings[0].as_ref(), strings[1].as_ref()));
}
[src/main.rs:14] ptr::eq(strings[0].as_ref(), strings[1].as_ref()) = false

当你有一个 Rc<RefCell<_>> 或其他具有内部可变性的类型时,这尤其糟糕,因为你可能期望修改其中一个项目会修改 所有 个项目.

另请参阅:

  • How can I get Serde to allocate strings from an arena during deserialization?