Is it safe to drop_in_place a pointer to a dangling ref?


I haven't read through all the meta discussion regarding cultural and philosophical aspects of UB, but last time I checked the question whether invalid references (and what kind of invalidity) causes immediate UB was still somewhat undecided (which does indicate one should usually be better off cauciously assuming stricter rules, but it's maybe a bit oversimplified to claim "this is 100% definite UB" for many things around invalid references).

And on the specific question of calling std::ptr::drop_in_place on a *mut &T where the *mut points to valid memory containing a &T whose lifetime has expired, given precedent of many a #[may_dangle] usage in the standard library, though off the top of my head I'm not sure what precise source to point to to validate this claim, my take would be to give a clear "yes, that's fine, you may do that".

The Rustonomicon mentions it in a small tangent in the section on PhantomData:

It's a scary feature, though.

Vec's Drop is implemented as:

unsafe impl<#[may_dangle] T, A: Allocator> Drop for Vec<T, A> {
    fn drop(&mut self) {
        unsafe {
            ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.as_mut_ptr(), self.len))
        // RawVec handles deallocation

Notice how the T may dangle, thus the ptr::drop_in_place may drop dangling references.

I was wondering if this is actually true and looks like MIRI seems to disagree with this! It finds UB when ptr::read is used but not with ptr::drop_in_place. I opened MIRI disagree with the documentation of `ptr::drop_in_place` · Issue #112015 · rust-lang/rust · GitHub for this.

1 Like