gpt4 book ai didi

rust - Rust生命周期子类型不适用于Cell

转载 作者:行者123 更新时间:2023-12-03 11:34:09 25 4
gpt4 key购买 nike

给定类型为Vec<&'static str>的值,我可以自由地将其转换为Vec<&'r str>,因为'r'static的子区域。这似乎适用于大多数类型,例如Vec,pairs等。但是,它不适用于CellRefCell之类的类型。具体来说,down_vec会编译,但是down_cell不会:

use std::cell::Cell;

fn down_vec<'p, 'r>(x: &'p Vec<&'static str>) -> &'p Vec<&'r str> {
x
}


fn down_cell<'p, 'r>(x: &'p Cell<&'static str>) -> &'p Cell<&'r str> {
x
}

给出错误:
error[E0308]: mismatched types
--> src/lib.rs:9:5
|
9 | x
| ^ lifetime mismatch
|
= note: expected reference `&'p std::cell::Cell<&'r str>`
found reference `&'p std::cell::Cell<&'static str>`
note: the lifetime `'r` as defined on the function body at 8:18...
--> src/lib.rs:8:18
|
8 | fn down_cell<'p, 'r>(x: &'p Cell<&'static str>) -> &'p Cell<&'r str> {
| ^^
= note: ...does not necessarily outlive the static lifetime

为什么这对于 Cell不起作用?编译器如何跟踪它不起作用?是否有其他方法可以使其正常工作?

最佳答案

CellRefCell不同,因为它们允许通过共享引用对内部值进行突变。

要了解为什么这很重要,我们可以编写一个函数,使用down_cell泄漏对释放内存的引用:

fn oops() -> &'static str {
let cell = Cell::new("this string doesn't matter");
let local = String::from("this string is local to oops");
let broken = down_cell(&cell); // use our broken function to rescope the Cell
broken.set(&local); // use the rescoped Cell to mutate `cell`
cell.into_inner() // return a reference to `local`
} // uh-oh! `local` is dropped here
oops不包含 unsafe块,但可以编译,因此为了防止访问释放的内存,编译器必须拒绝 down_cell

之所以在类型级别进行解释,是因为 Cell<T>RefCell<T>包含 UnsafeCell<T>,这使它们在 T中不变,而 Box<T>Vec<T>T中是协变的。
VecBox和其他类似容器的结构之所以可以协变的原因是因为这些容器需要 &mut访问权才能对其内容进行变异,而 &mut T本身在 T中是不变的。您无法使用 oops编写类似于 down_vec的函数-编译器不允许这样做。

引用
  • Rustonomicon的Subtyping and Variance
  • How does the Rust compiler know `Cell` has internal mutability?
  • Why does linking lifetimes matter only with mutable references?
  • 关于rust - Rust生命周期子类型不适用于Cell,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62085032/

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