如何为包含原始指针的结构强制执行生命周期?
How can I enforce lifetimes for a struct that contains a raw pointer?
Editor's note: This code no longer compiles in Rust 1.0 with the error parameter `'a` is never used
. The reason for this error is exactly because of the problem demonstrated below, so the (updated) solution remains applicable.
extern crate core;
use core::ops::{Deref, DerefMut};
struct MutPtr<'a, T> {
ptr: *mut T,
}
impl<'a, T> MutPtr<'a, T> {
fn new<'b>(value: &'b mut T) -> MutPtr<'b, T> {
MutPtr { ptr: value }
}
}
impl<'a, T> Deref for MutPtr<'a, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &(*self.ptr) }
}
}
impl<'a, T> DerefMut for MutPtr<'a, T> {
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut (*self.ptr) }
}
}
struct Bar {
v: i32,
}
fn err<'a>() -> MutPtr<'a, Bar> {
let mut b = Bar { v: 42 };
MutPtr::new(&mut b) // Shouldn't this throw an error?
}
fn main() {
let mut b = Bar { v: 42 };
let mut ptr_b = MutPtr::new(&mut b);
let mut ptr_b1 = MutPtr::new(&mut b);
ptr_b.v = 10;
println!("{}", b.v);
ptr_b1.v = 21;
println!("{}", b.v);
}
此代码块引起了一些混乱:
fn err<'a>() -> MutPtr<'a, Bar> {
let mut b = Bar { v: 42 };
MutPtr::new(&mut b) // Shouldn't this throw an error?
}
为什么编译?
当我打电话时
MutPtr::new(&mut b)
它不应该有b
的生命周期吗?我预计会出现编译错误,因为生命周期 'a
比 MutPtr<'b, Bar>
.
的生命周期长
我想你要找的是 core::marker::PhantomData
(也可以在 std::marker::PhantomData
中找到)。
发生的情况是编译器没有为指针变量分配任何生命周期,因此编译器不知道如何约束结构的生命周期。
方法是在你的结构中添加一个标记 PhantomData<&'a ()>
,它告诉编译器整个结构的生命周期可能不会超过 'a
(实际上,假装 MutPtr<'a, T>
中有一个 &'a ()
字段,即使它没有)。
所以最后你的结构应该是这样的:
struct MutPtr<'a, T> {
ptr: *mut T,
_covariant: PhantomData<&'a ()>,
}
impl<'a, T> MutPtr<'a, T> {
fn new(value: &'a mut T) -> MutPtr<'a, T> {
MutPtr {
ptr: value,
_covariant: PhantomData,
}
}
}
这样你就得到了预期的错误 b does not live long enough
。
Editor's note: This code no longer compiles in Rust 1.0 with the error
parameter `'a` is never used
. The reason for this error is exactly because of the problem demonstrated below, so the (updated) solution remains applicable.
extern crate core;
use core::ops::{Deref, DerefMut};
struct MutPtr<'a, T> {
ptr: *mut T,
}
impl<'a, T> MutPtr<'a, T> {
fn new<'b>(value: &'b mut T) -> MutPtr<'b, T> {
MutPtr { ptr: value }
}
}
impl<'a, T> Deref for MutPtr<'a, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &(*self.ptr) }
}
}
impl<'a, T> DerefMut for MutPtr<'a, T> {
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut (*self.ptr) }
}
}
struct Bar {
v: i32,
}
fn err<'a>() -> MutPtr<'a, Bar> {
let mut b = Bar { v: 42 };
MutPtr::new(&mut b) // Shouldn't this throw an error?
}
fn main() {
let mut b = Bar { v: 42 };
let mut ptr_b = MutPtr::new(&mut b);
let mut ptr_b1 = MutPtr::new(&mut b);
ptr_b.v = 10;
println!("{}", b.v);
ptr_b1.v = 21;
println!("{}", b.v);
}
此代码块引起了一些混乱:
fn err<'a>() -> MutPtr<'a, Bar> {
let mut b = Bar { v: 42 };
MutPtr::new(&mut b) // Shouldn't this throw an error?
}
为什么编译?
当我打电话时
MutPtr::new(&mut b)
它不应该有b
的生命周期吗?我预计会出现编译错误,因为生命周期 'a
比 MutPtr<'b, Bar>
.
我想你要找的是 core::marker::PhantomData
(也可以在 std::marker::PhantomData
中找到)。
发生的情况是编译器没有为指针变量分配任何生命周期,因此编译器不知道如何约束结构的生命周期。
方法是在你的结构中添加一个标记 PhantomData<&'a ()>
,它告诉编译器整个结构的生命周期可能不会超过 'a
(实际上,假装 MutPtr<'a, T>
中有一个 &'a ()
字段,即使它没有)。
所以最后你的结构应该是这样的:
struct MutPtr<'a, T> {
ptr: *mut T,
_covariant: PhantomData<&'a ()>,
}
impl<'a, T> MutPtr<'a, T> {
fn new(value: &'a mut T) -> MutPtr<'a, T> {
MutPtr {
ptr: value,
_covariant: PhantomData,
}
}
}
这样你就得到了预期的错误 b does not live long enough
。