Search code examples
rustundefined-behaviorunsaferaw-pointer

Is it undefined behavior to dereference a *mut T cast to *mut ManuallyDrop<T>?


According to the docs, ManuallyDrop<T> is a zero-cost wrapper. Does that mean I can dereference a raw pointer to ManuallyDrop<T> casted from a raw pointer to T?


Solution

  • ManuallyDrop is declared as #[repr(transparent)]:

    #[stable(feature = "manually_drop", since = "1.20.0")]
    #[lang = "manually_drop"]
    #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
    #[repr(transparent)]
    pub struct ManuallyDrop<T: ?Sized> {
        value: T,
    }
    

    #[repr(transparent)] is described as:

    The attribute can be applied to a newtype-like structs that contains a single field. It indicates that the newtype should be represented exactly like that field's type, i.e., the newtype should be ignored for ABI purpopses [sic]: not only is it laid out the same in memory, it is also passed identically in function calls.

    [...]

    PtrWithCustomZst is also represented exactly like *const Foo

    I believe that it is safe to perform this transformation.


    The real question is why would you want to do this? Having a pointer to a ManuallyDrop structure seems rather pointless. If you have a pointer to a T, the underlying value won't be dropped to start with. If you convert the pointer to a reference (while ensuring you uphold the rules of references), the reference won't drop the underlying value either.