当涉及原始指针时,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()
参数的生命周期推断?原始指针没有生命周期那么编译器如何知道它应该使用协方差使 cell
和 new_value
具有相同的生命周期?
How does the assignment inside the unsafe block affect the lifetime inference for the parameters of set()
?
它不是——而且这甚至不是特定于原始指针或 unsafe
。函数体从不 影响函数签名的任何方面(除了async fn
s,这里不相关)。
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
类型的字段。协变是大多数泛型类型的“典型”情况。
因此,您的代码不可靠,因为 MyCell
在 T
上是协变的,但在 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
中不变。这两个在这里都是必需的。
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()
参数的生命周期推断?原始指针没有生命周期那么编译器如何知道它应该使用协方差使 cell
和 new_value
具有相同的生命周期?
How does the assignment inside the unsafe block affect the lifetime inference for the parameters of
set()
?
它不是——而且这甚至不是特定于原始指针或 unsafe
。函数体从不 影响函数签名的任何方面(除了async fn
s,这里不相关)。
Raw pointers does not have lifetime then how does the compiler know it should make
cell
andnew_value
have the same lifetime using covariance?
听起来你误读了一些建议。在您的代码中,Cell<T>
在 T
中是不变的,但是对于 interior-mutable 类型来说,它必须是 invariant (不是协变的) ) 在类型参数中。在您的代码中,编译器推断 T
的协方差,因为 MyCell
包含一个简单的 T
类型的字段。协变是大多数泛型类型的“典型”情况。
因此,您的代码不可靠,因为 MyCell
在 T
上是协变的,但在 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
中不变。这两个在这里都是必需的。