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>
impl<D: DropMarkerKind, T: ForLifetime> Unsafe<D, T>
Sourcepub fn wrap_binder_manually_drop(value: T::Of<'_>) -> Selfwhere
NoDropGlue: Is<ItSelf = D>,
pub fn wrap_binder_manually_drop(value: T::Of<'_>) -> Selfwhere
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<'_>>()
-
If so, you will need to call
Self::manually_drop_in_place()eventually to avoid that. -
When
T::Of<'_> : Copy, consider usingSelf::wrap_binder_copy()instead.
Sourcepub fn wrap_binder_copy<'input>(value: T::Of<'input>) -> Self
pub fn wrap_binder_copy<'input>(value: T::Of<'input>) -> Self
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.
Sourcepub unsafe fn wrap_binder_with_drop_glue(value: T::Of<'_>) -> Selfwhere
MayDrop: Is<ItSelf = D>,
pub unsafe fn wrap_binder_with_drop_glue(value: T::Of<'_>) -> Selfwhere
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
valuebecomingT::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
SAFETYproperty much alike that ofPin::new_unchecked().
Sourcepub unsafe fn unwrap_binder<'lt>(self) -> T::Of<'lt>where
'lt:,
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.
Sourcepub unsafe fn unwrap_binder_ref<'r, 'lt>(&'r self) -> &'r T::Of<'lt>where
'lt:,
'r:,
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.
Sourcepub unsafe fn unwrap_binder_mut<'r, 'lt>(&'r mut self) -> &'r mut T::Of<'lt>where
'lt:,
'r:,
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.
Sourcepub 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:,
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.
Sourcepub unsafe fn manually_drop_in_place(&mut self)where
NoDropGlue: Is<ItSelf = D>,
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().
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!");
})pub fn with_unwrapped_binder<R>(self, scope: impl FnOnce(T::Of<'_>) -> R) -> R
pub fn with_unwrapped_binder_ref<'r, R>( &'r self, scope: impl FnOnce(&'r T::Of<'_>) -> R, ) -> R
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>
impl<D: DropMarkerKind, T: ForLifetime> Drop for Unsafe<D, T>
impl<D: DropMarkerKind, T: ForLifetime> Send for Unsafe<D, T>
impl<D: DropMarkerKind, T: ForLifetime> Sync for Unsafe<D, T>
impl<T: ForLifetime> Unpin for Unsafe<MayDrop, T>
Pinning projection (see Self::unwrap_binder_pin_mut()).
impl<T: ForLifetime> Unpin for Unsafe<NoDropGlue, T>
No pinning projection whatsoever (unconditionally Unpin).