如何为包含原始指针的结构强制生命周期?

时间:2015-01-14 09:18:32

标签: rust

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&gt;

1 个答案:

答案 0 :(得分:4)

我认为您要找的是core::marker::ContravariantLifetime(也可在std::marker::ContravariantLifetime中找到) 发生的事情是编译器没有为指针变量分配任何生命周期,因此全局结构的生命周期不受内部的限制(在你的情况下应该是这样)

这样做的方法是在结构中添加一个标记ContravariantLifetime,告诉编译器如果推断的生命周期长于标记,那么编译器会将整个结构的生命周期缩短到标记中的生命周期。在标记中。

所以最后你的结构应该是这样的:

struct MutPtr<'a,T>{
    ptr: *mut T,
    marker: ContravariantLifetime<'a>,
}

impl<'a,T> MutPtr<'a,T>{
    fn new<'b>(value: &'b mut T) -> MutPtr<'b,T>{
        MutPtr{ptr: value, marker: ContravariantLifetime::<'b>}
    }
}

这样您就会得到预期的错误b does not live long enough