Unsafe

Struct Unsafe 

Source
pub struct Unsafe<D: DropMarkerKind, T: ForLifetime> { /* private fields */ }
Expand description

Stable rust polyfill of unsafe<'lt> … binders, with a fixed arity of 1.

Important note: only use this type name when wanting to access the associated functions. Most notably, the Unsafe::wrap_binder…() constructors.

Otherwise, the eponymous Unsafe![] macro is to be used.

§Memory layout

This is a SemVer-guaranteed #[repr(transparent)] around its inner T::Of<'_> value.

§Guarantees unsafe code may rely on

Given this, if you know that for some wrapper type Coll, Coll<&'a str> is sound to transmute into Coll<&'b str>, for instance because the Coll wrapper type makes guarantees about its own layout and API based on that of the <T> generic type, then it will be sound to transmute an &'a str-stemming Coll<Unsafe<_, T>> into a Coll<T::Of<'b>>. And so on for other T::Of<'_> lifetime-generic wrappee types.

  • You should generally not need this, thanks to the various Self::unwrap_binder…() APIs already exposed by this type.

  • In any “sane wrapper type” case, the property required herein is met.

    But a counter-example would be the following:

    Click to show
    struct Helix<T: Shenanigans>(
        <T as Shenanigans>::Assoc,
    );
    
    trait Shenanigans {
        type Assoc;
    }
    
    impl Shenanigans for &str {
        type Assoc = bool;
    }
    
    impl<D: DropMarkerKind> Shenanigans for Unsafe![D, &str] {
        type Assoc = u8;
    }
    
    let helix: Helix<Unsafe![DropMarker::NoDropGlue, &str]> = Helix(2_u8);
    let Helix::<&str>(bool) = unsafe {
        ::core::mem::transmute::<
            Helix<Unsafe![<'any> &'any str]>,
            Helix<                 &'_ str >,
        >(helix)
    }; // UB! `bool: bool`'s bitpattern is `2_u8`!

Implementations§

Source§

impl<D: DropMarkerKind, T: ForLifetime> Unsafe<D, T>

Source

pub fn wrap_binder_manually_drop(value: T::Of<'_>) -> Self
where NoDropGlue: Is<ItSelf = D>,

Constructs an Unsafe<_, T> with DropMarker::NoDropGlue, i.e., with no drop glue attached.

This means that a memory leak may ensue when ::core::mem::needs_drop::<T::Of<'_>>()

Source

pub fn wrap_binder_copy<'input>(value: T::Of<'input>) -> Self
where NoDropGlue: Is<ItSelf = D>, T::Of<'input>: Copy,

Constructs an Unsafe<_, T> with a DropMarker which does not matter. This is fine since this requires T::Of<'input> : Copy to hold, so there cannot be actual drop glue.

Source

pub unsafe fn wrap_binder_with_drop_glue(value: T::Of<'_>) -> Self
where MayDrop: Is<ItSelf = D>,

Constructs an Unsafe<_, T> with DropMarker::MayDrop, i.e., with drop glue attached to it.

The very point of using this wrapper is to erase a lifetime, so this API can result in access to dangling data (UAF) when misused!

§Safety

It must be sound to call Self::manually_drop_in_place() when this instance is dropped / goes out of scope. This soundness property is usually the result of immediately wrapping this instance in an aptly-lifetime infected or properly self-referential struct.

Moreover, it must be sound to access the inner value as long as this value lives. This is indeed the case due to the existence of the scoped/existential-lifetime Self::with_unwrapped_binder…() APIs.

  • A subtle corollary is that you can only relinquish owned access of this instance to an arbitrary API if you are fine with the value becoming T::Of<'static>.

    Or phrased differently: you can only soundly call this constructor as an owner (who wraps the whole thing in a sound API). This is a very non-local SAFETY property much alike that of Pin::new_unchecked().

Source

pub unsafe fn unwrap_binder<'lt>(self) -> T::Of<'lt>
where 'lt:,

By value, imbue back the binder with a concrete 'lt of your choice.

§Safety

Pick 'lt wisely: it ought to match the original input lifetime used when doing Self::wrap_binder…(), or something semantically equivalent.

Using 'input upon Self::wrap_binder…() construction and 'lt here is tantamount to having transmuted the 'input lifetime to 'lt.

Source

pub unsafe fn unwrap_binder_ref<'r, 'lt>(&'r self) -> &'r T::Of<'lt>
where 'lt:, 'r:,

By &-reference, imbue back the binder with a concrete 'lt of your choice.

§Safety

Pick 'lt wisely: it ought to match the original input lifetime used when doing Self::wrap_binder…(), or something semantically equivalent.

Using 'input upon Self::wrap_binder…() construction and 'lt here is tantamount to having transmuted the 'input lifetime to 'lt.

Source

pub unsafe fn unwrap_binder_mut<'r, 'lt>(&'r mut self) -> &'r mut T::Of<'lt>
where 'lt:, 'r:,

By &mut-reference, imbue back the binder with a concrete 'lt of your choice.

§Safety

Pick 'lt wisely: it ought to match the original input lifetime used when doing Self::wrap_binder…(), or something semantically equivalent.

Using 'input upon Self::wrap_binder…() construction and 'lt here is tantamount to having transmuted the 'input lifetime to 'lt.

Source

pub unsafe fn unwrap_binder_pin_mut<'r, 'lt>( self: Pin<&'r mut Self>, ) -> Pin<&'r mut T::Of<'lt>>
where MayDrop: Is<ItSelf = D>, 'lt:, 'r:,

By &pin mut-reference, imbue back the binder with a concrete 'lt of your choice.

This is effectively a pinning projection (on top of lifetime transmutation).

§Safety

Pick 'lt wisely: it ought to match the original input lifetime used when doing Self::wrap_binder…(), or something semantically equivalent.

Using 'input upon Self::wrap_binder…() construction and 'lt here is tantamount to having transmuted the 'input lifetime to 'lt.

Source

pub unsafe fn manually_drop_in_place(&mut self)
where NoDropGlue: Is<ItSelf = D>,

Manually drop in place the value provided to Self::wrap_binder_manually_drop() (since it would otherwise not be dropped).

Note: this API is only available in the DropMarker::NoDropGlue case. If you nonetheless wish to do this in the DropMarker::MayDrop case despite the resulting humongous risk of double dropping, then do so the usual way, i.e., using ::core::ptr::drop_in_place() or your own ::core::mem::ManuallyDrop::drop().

Source§

impl<T: ForLifetime> Unsafe<MayDrop, T>

Convenience non-unsafe APIs, courtesy of the unsafe promise provided by Unsafe::wrap_binder_with_drop_glue().

Uses a scoped API to emulate an existential lifetime.

§Example

use ::unsafe_binders::prelude::*;

let static_: &'static str = "Hello, World!";
let erased: Unsafe![DropMarker::MayDrop, &str] = unsafe {
    // Safety: `&str` is covariant, and we have a `&'static str`, so we may
    // as well have a `&'any str`.
    Unsafe::wrap_binder_with_drop_glue(static_)
};

// Safely access the value!
erased.with_unwrapped_binder_ref(|&s| {
    assert_eq!(s, "Hello, World!");
})
Source

pub fn with_unwrapped_binder<R>(self, scope: impl FnOnce(T::Of<'_>) -> R) -> R

Source

pub fn with_unwrapped_binder_ref<'r, R>( &'r self, scope: impl FnOnce(&'r T::Of<'_>) -> R, ) -> R

Source

pub fn with_unwrapped_binder_mut<'r, R>( &'r mut self, scope: impl FnOnce(&'r mut T::Of<'_>) -> R, ) -> R

Trait Implementations§

Source§

impl<D: DropMarkerKind, T: ForLifetime> Drop for Unsafe<D, T>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl<D: DropMarkerKind, T: ForLifetime> Send for Unsafe<D, T>
where for<'any> T::Of<'any>: Send,

Source§

impl<D: DropMarkerKind, T: ForLifetime> Sync for Unsafe<D, T>
where for<'any> T::Of<'any>: Sync,

Source§

impl<T: ForLifetime> Unpin for Unsafe<MayDrop, T>
where for<'any> T::Of<'any>: Unpin,

Pinning projection (see Self::unwrap_binder_pin_mut()).

Source§

impl<T: ForLifetime> Unpin for Unsafe<NoDropGlue, T>

No pinning projection whatsoever (unconditionally Unpin).

Auto Trait Implementations§

§

impl<D, T> Freeze for Unsafe<D, T>
where <T as ForLifetime>::Of<'static>: Freeze,

§

impl<D, T> !RefUnwindSafe for Unsafe<D, T>

§

impl<D, T> !Unpin for Unsafe<D, T>

§

impl<D, T> !UnwindSafe for Unsafe<D, T>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Is for T
where T: ?Sized,

Source§

type EqTo = T

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.