gpt4 book ai didi

rust - 为什么我的 RefCell 零成本替代方案不是实现内部可变性的标准方法?

转载 作者:行者123 更新时间:2023-12-02 07:57:53 29 4
gpt4 key购买 nike

我一直在思考为什么 Rust 中的内部可变性在大多数情况下需要运行时检查(例如 RefCell )。看起来我找到了一个没有运行时成本的安全替代方案。我调用类型 SafeCell (主要是因为它是围绕 UnsafeCell 的安全包装器),并且它允许您将任何函数应用于包装的值而没有引用转义的风险:

struct SafeCell<T> {
inner: UnsafeCell<T>,
}

impl<T> SafeCell<T> {
pub fn new(value: T) -> Self {
Self {
inner: UnsafeCell::new(value),
}
}

pub fn apply<R, F>(&self, fun: F) -> R
where
F: FnOnce(&mut T) -> R,
{
// Reference below has a lifetime of the current scope, so if
// user tries to save it somewhere, borrow checker will catch this.
let reference: &mut T = unsafe { &mut *self.inner.get() };
fun(reference)
}
}
这种类型可用于内部可变性,如下所示:
pub struct MySet {
set: HashSet<i32>,
unique_lookups: SafeCell<HashSet<i32>>,
}

impl MySet {
pub fn contains(&self, value: i32) -> bool {
self.unique_lookups.apply(|lookups| lookups.insert(value));
self.set.contains(value)
}

pub fn unique_lookups_count(&self) -> usize {
self.unique_lookups.apply(|lookups| lookups.len())
}
}
或与 Rc一起使用:
fn foo(rc: Rc<SafeCell<String>>) {
rc.apply(|string| {
if string.starts_with("hello") {
string.push_str(", world!")
}
println!("{}", string);
});
}
Playground
  • 这种类型是否存在任何安全/健全性问题?
  • 如果不是,为什么这样的类型不是实现内部可变性的标准方法?看起来和RefCell一样好用同时提供静态生命周期检查而不是运行时检查。
  • 最佳答案

    您的 API 中没有任何内容阻止用户调用 apply再次在提供给 apply 的闭包中.这允许对同一数据有多个同时的可变引用,这是未定义的行为。

    let x = SafeCell::new(0);
    x.apply(|y| {
    x.apply(|z| {
    // `y` and `z` are now both mutable references to the same data
    // UB!
    *y = 1;
    *z = 2;
    })
    });
    x.apply(|y| println!("x: {}", y));

    (playground)

    当 Miri 看到第二个可变引用时,它正确地调用了它。

    error: Undefined Behavior: not granting access to tag <untagged> because incompatible item is protected: [Unique for <1651> (call 1230)]
    --> src/main.rs:20:42
    |
    20 | let reference: &mut T = unsafe { &mut *self.inner.get() };
    | ^^^^^^^^^^^^^^^^^^^^^^ not granting access to tag <untagged> because incompatible item is protected: [Unique for <1651> (call 1230)]
    |

    关于rust - 为什么我的 RefCell 零成本替代方案不是实现内部可变性的标准方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61159541/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com