Diz*_*tul 2 unsafe lifetime rust raw-pointer
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);
}
Run Code Online (Sandbox Code Playgroud)
当调用时cell.set(&local),假设cellis'x和'&localis ,我被告知协方差规则将更改from到 的'y类型。cell&MyCell<'x, &i32>&MyCell<'y, &i32>
unsafe 块内的赋值如何影响 的参数的生命周期推断set()?原始指针没有生命周期那么编译器如何知道它应该使用协方差cell具有new_value相同的生命周期?
Kev*_*eid 10
\n\nunsafe 块内的赋值如何影响 的参数的生命周期推断
\nset()?
它不\xe2\x80\x94,这甚至不是特定于原始指针或unsafe. 函数体永远不会影响函数签名的任何方面(除了与async fn此处无关的 s )。
\n\n原始指针没有生命周期那么编译器如何知道它应该使用协方差
\ncell具有new_value相同的生命周期?
听起来你误读了一些建议。在您的代码中,Cell<T>是 不变的T,但为了使内部可变类型健全,它在类型参数中必须是不变的(不是协变的)。在您的代码中,编译器推断 的 协方差T因为MyCell包含一个简单类型 的字段T。对于大多数泛型类型,协方差是 \xe2\x80\x9c典型\xe2\x80\x9d 情况。
因此,您拥有的代码是不健全的,因为MyCell它是协变的T,但必须是不变的T。
您的代码也不健全,因为在 的实现中set(),您正在创建对T,的不可变引用&self.value,然后写入其指示对象。不管你怎么做,这都是\xe2\x80\x9c未定义的行为\xe2\x80\x9d ,因为&self.value向编译器/优化器创建断言,在引用被删除之前,指向的内存不会被修改。
如果您想重新实现标准库Cell,则必须像标准库一样使用UnsafeCell原语进行操作:
pub struct Cell<T: ?Sized> {\n value: UnsafeCell<T>,\n}\nRun Code Online (Sandbox Code Playgroud)\nUnsafeCell这就是您选择退出&不变性保证的方式:创建一个&UnsafeCell<T> 不断言T不会被改变。它在 中也是不变的T,这会自动使包含类型在 中不变T。在这里,这两者都是必要的。
| 归档时间: |
|
| 查看次数: |
652 次 |
| 最近记录: |