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

标签 rust lifetime borrow-checker

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 的生命周期吗? ?我预计会出现编译错误,因为生命周期 'aMutPtr<'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 .

关于rust - 如何为包含原始指针的结构强制执行生命周期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27939355/

相关文章:

reference - 匹配表达式如何解释值与引用?

rust - 在 Rust 中通过一个 crate 访问另一个 crate

performance - 加速计数器游戏

rust - 在 Rust 中返回一个引用和被引用的对象

string - 如何传递修改后的字符串参数?

rust - 无法搬出借用的内容和Builder模式

Rust 借用检查器在 if 语句中抛出错误

rust - 为什么不能将借入的值放在互斥对象后面并将其传递给另一个线程?

javascript - 在 javascript 方法中定义的数组的生命周期

rust - “outlives” 关系和实际范围