gpt4 book ai didi

rust - 有没有办法告诉 Rust 的 drop checker 我们有效地拥有一个 `T` 而没有它在通用参数中?

转载 作者:行者123 更新时间:2023-12-03 11:23:57 25 4
gpt4 key购买 nike

假设我想写这样的代码:

struct Inspector<'a>(&'a u8);

struct Foo<'a> {
value: Box<u8>,
inspector: Option<Inspector<'a>>,
}

fn main() {
let mut foo = Foo { value: Box::new(0), inspector: None };
foo.inspector = Some(Inspector(&foo.value));
}
playground
目前,Rust 编译器允许我这样做,只要我不添加 Drop Inspector 的实现.
如果我添加一个,则会出现以下编译时错误:

foo.value dropped while still borrowed.

Borrow might be used when foo is dropped and runs the destructor for type Foo<'_>


这显然是正确的。事实上,我从 the nomicon 中取了这个例子。 .
现在,这是我的问题。假设我有一个 Box 的奇怪实现没有任何 T在其类型参数中。
/// An heap-allocated `T` without generic parameters.
struct MyBox {
data: NonNull<u8>,

/// SAFETY:
/// Caller must ensure the value will not be
/// used again.
drop_fn: unsafe fn(*mut u8),

layout: Layout,
}

impl MyBox {
fn new<T>(val: T) -> Self {
if mem::size_of::<T>() == 0 {
panic!("T is a ZST");
}

let layout = Layout::new::<T>();
let data = NonNull::new(unsafe { alloc(layout) })
.unwrap_or_else(|| handle_alloc_error(layout));

// pointer refers to uninit owned memory
unsafe { data.cast::<T>().as_ptr().write(val) };

Self {
data,
// SAFETY: See `drop_fn` field for safety guarantees
drop_fn: |data| unsafe { drop_in_place(data as *mut T) },
layout,
}
}

/// Caller must ensure that this box owns a `T`.
unsafe fn trust_mut<T>(&mut self) -> &mut T {
&mut *self.data.cast().as_ptr()
}
}

impl Drop for MyBox {
fn drop(&mut self) {
// SAFETY: Value will not be used again
unsafe { (self.drop_fn)(self.data.as_ptr()) }
unsafe { dealloc(self.data.as_ptr(), self.layout) };
}
}
但这一次,Rust 的 drop checker 不知道 MyBox会掉一个 T当它的析构函数被调用时。这使我能够编写这个不健全的代码:
pub struct Inspector<'a>(&'a u8);

impl Drop for Inspector<'_> {
fn drop(&mut self) {
/* Could try to inspect `self.0` here which might have been dropped */
}
}

pub struct Foo<'a> {
value: Box<u8>,
inspector: Option<Inspector<'a>>,
}

fn main() {
let mut b = MyBox::new(Foo {
value: Box::new(0),
inspector: None,
});

let foo: &mut Foo = unsafe { b.trust_mut() };
foo.inspector = Some(Inspector(&foo.value)); // No error occurs here
}
playground
由此,我的问题很简单:有没有办法告诉丢弃检查器,当它被丢弃时,将生命周期限制在对象上是不行的?因为我基本上需要的是类似 PhantomData<T> 的东西没有 T .

最佳答案

我可以用这个做其他讨厌的事情 MyBoxDrop无关的...

fn main() {
let mut vec: Vec<i32> = vec![42];
let mut b = MyBox::new(&vec[0]); // T is &i32
{
let val: &mut &i32 = unsafe { b.trust_mut() };
println!("{}", *val);
}
vec[0] = 1337; // I can mutate `vec[0]` even though `vec[0]` is borrowed by `b`
{
let val: &mut &i32 = unsafe { b.trust_mut() };
println!("{}", *val);
}
}
问题是 MyBox完全删除有关 T 中借用的任何信息.有两种方法可以解决这个问题:
  • 严格的选项是更改 <T><T: 'static>MyBox::newMyBox::trust_mut .这将阻止 T 中的值借用任何非 'static数据。
  • 灵活的选项是向 MyBox 添加生命周期参数。 ,然后更改 <T><T: 'a>MyBox::newMyBox::trust_mut .如果你想要严格选项的效果,只需使用 MyBox<'static> .
  • use std::alloc::{Layout, alloc, dealloc, handle_alloc_error};
    use std::marker::PhantomData;
    use std::mem::size_of;
    use std::ptr::{self, NonNull};

    /// An heap-allocated `T` without generic parameters.
    struct MyBox<'a> {
    data: NonNull<u8>,

    /// SAFETY:
    /// Caller must ensure the value will not be
    /// used again.
    drop_fn: unsafe fn(*mut u8),

    layout: Layout,

    _borrow: PhantomData<&'a ()>,
    }

    impl<'a> MyBox<'a> {
    fn new<T: 'a>(val: T) -> Self {
    if size_of::<T>() == 0 {
    panic!("T is a ZST");
    }

    let layout = Layout::new::<T>();
    let data = NonNull::new(unsafe { alloc(layout) })
    .unwrap_or_else(|| handle_alloc_error(layout));

    // pointer refers to uninit owned memory
    unsafe { data.cast::<T>().as_ptr().write(val) };

    Self {
    data,
    // SAFETY: The caller must ensure that the value will not
    // be using the value again.
    drop_fn: |data| unsafe { ptr::drop_in_place(data as *mut T) },
    layout,
    _borrow: PhantomData,
    }
    }

    /// Caller must ensure that this box owns a `T`.
    unsafe fn trust_mut<T: 'a>(&mut self) -> &mut T {
    &mut *self.data.cast().as_ptr()
    }
    }

    关于rust - 有没有办法告诉 Rust 的 drop checker 我们有效地拥有一个 `T` 而没有它在通用参数中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65866583/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com