为什么 `Deref` 没有在 `Cell<T>` 上实现?

Sel*_*elf 6 rust

Cell 只是一个内联存储/包装类型,它控制内部类型 T 的可变性/访问语义并提供内部可变性功能。从Rust 文档 Deref来看,该类型并未实现Cell<T>。为什么是这样 ?的实例Cell<T>始终处于有效状态(内存始终有效且已初始化)。这意味着在实施时Deref不可能Cell<T>出现恐慌,这是实施的要求之一Deref

提供一个Derefimpl forCell<T>会很方便。

FZs*_*FZs 17

但这是不健全的!

的前提Cell是它永远不会给出对其内容的引用(事实上,这就是它的兄弟RefCell所做的),因此对它的所有读写操作都是原子的1

作为其实现的一部分,Cell有一个set具有以下签名的方法:

fn set(&self, val: T)
Run Code Online (Sandbox Code Playgroud)

...这会更改 的值,即共享引用2&Cell<T>后面的单元格的值。这就是内部可变性的工作原理。

现在想象一下您可以创建对以下内容的引用Cell

let cell = Cell::new(1);

let one: &i32 = &*cell;
Run Code Online (Sandbox Code Playgroud)

...其他人调用了该set方法:

cell.set(2);
Run Code Online (Sandbox Code Playgroud)

现在我们已经改变了共享引用()所指向的数据&T,即 UB 3

println!("one = {}", *one); // one = 2 !!!
Run Code Online (Sandbox Code Playgroud)

游乐场链接

1:不是“线程安全”意义上的
2:它可以通过使用UnsafeCell一个内置编译器来很好地做到这一点:“相信我编译器,我可以强制执行借用规则,所以你不必这样做”
3:在(之外不知道)UnsafeCell&TCell