当涉及原始指针时,Rust 如何推断生命周期?

How does Rust infer lifetime while raw pointers are involved?

struct MyCell<T> {
    value: T
}

impl<T> MyCell<T> {
    fn new(value: T) -> Self {
        MyCell { value }
    }
    
    fn get(&self) -> &T {
        &self.value
    }
    
    fn set(&self, new_value: T) {
        unsafe { 
            *(&self.value as *const T as *mut T) = new_value; 
        }
    }
}

fn set_to_local(cell: &MyCell<&i32>) {
    let local = 100;
    cell.set(&local);
}

fn main() {
    let cell = MyCell::new(&10);
    set_to_local(&cell);
}

当调用cell.set(&local)时,假设cell'x'&local'y,我被告知协方差规则会改变类型cell&MyCell<'x, &i32>&MyCell<'y, &i32>

不安全块内的赋值如何影响set()参数的生命周期推断?原始指针没有生命周期那么编译器如何知道它应该使用协方差使 cellnew_value 具有相同的生命周期?

How does the assignment inside the unsafe block affect the lifetime inference for the parameters of set()?

它不是——而且这甚至不是特定于原始指针或 unsafe。函数体从不 影响函数签名的任何方面(除了async fns,这里不相关)。

Raw pointers does not have lifetime then how does the compiler know it should make cell and new_value have the same lifetime using covariance?

听起来你误读了一些建议。在您的代码中,Cell<T>T 中是不变的,但是对于 interior-mutable 类型来说,它必须是 invariant (不是协变的) ) 在类型参数中。在您的代码中,编译器推断 T 的协方差,因为 MyCell 包含一个简单的 T 类型的字段。协变是大多数泛型类型的“典型”情况。

因此,您的代码不可靠,因为 MyCellT 上是协变的,但在 T 上必须是不变的。

您的代码 不可靠,因为在 set() 的实现中,您正在创建对 T&self.value,然后写给它的指称。这是“未定义的行为”不管你怎么做, 因为创建 &self.value 向 compiler/optimizer 断言 pointed-to 内存不会修改直到引用被删除。

如果你想重新实现标准库的 Cell,你必须像标准库那样使用 UnsafeCell 原语:

pub struct Cell<T: ?Sized> {
    value: UnsafeCell<T>,
}

UnsafeCell 是您选择退出 & 的不变性保证的方式:创建 &UnsafeCell<T> 不会 断言 T不会变异。它在 T 中也是不变的,它自动使包含类型在 T 中不变。这两个在这里都是必需的。