Stream: t-lang/wg-unsafe-code-guidelines

Topic: Is ptr::read followed by mem::forget valid?


Konrad Borowski (Jul 31 2019 at 09:36, on Zulip):
use std::mem;
use std::ptr;

struct X(Box<i32>);

impl X {
    fn into_inner(self) -> Box<i32> {
        unsafe {
            let a = ptr::read(&self.0);
            mem::forget(self);
            a
        }
    }
}

fn main() {
    println!("{}", X(Box::new(3)).into_inner());
}

Miri complains (Miri evaluation error: trying to reborrow for Unique, but parent tag <1843> does not have an appropriate item in the borrow stack) about this, it's used by https://github.com/abonander/buf_redux/blob/bc614ae2a87442f3edc750108d8f1488037d3a39/src/lib.rs#L631 to retrieve certain struct fields without calling destructor. Should it work this way?

RalfJ (Jul 31 2019 at 10:12, on Zulip):

@Konrad Borowski ah, I have seen this pattern before. the issue is that mem::forget is just like any other function call, so when you pass self to mem::forget you are basically saying "this is the only pointer to that memory, make other pointers invalid". At least that's the case with current Stacked Borrows, which is still experimental.

RalfJ (Jul 31 2019 at 10:13, on Zulip):

The recommended way to avoid that is to entirely avoid mem::forget and use ManuallyDrop instead

RalfJ (Jul 31 2019 at 10:14, on Zulip):

so for your code, something like

let a = ManuallyDrop::new(self);
ptr::read(&*a);
RalfJ (Jul 31 2019 at 10:14, on Zulip):

also see https://github.com/rust-lang/rust/pull/62610

Last update: Nov 19 2019 at 18:30UTC