Skip to content

Commit

Permalink
Add support for destructuring unaligned pointers
Browse files Browse the repository at this point in the history
  • Loading branch information
djkoloski committed Apr 15, 2022
1 parent f87f407 commit 3ab52ff
Show file tree
Hide file tree
Showing 2 changed files with 171 additions and 101 deletions.
119 changes: 87 additions & 32 deletions src/impls.rs
Original file line number Diff line number Diff line change
@@ -1,60 +1,73 @@
use {
crate::{Aligned, AlignedMut, Destructure, Restructure, StructuralPinning},
crate::{Destructure, Restructure, StructuralPinning},
::core::{
cell::{Cell, UnsafeCell},
mem::{ManuallyDrop, MaybeUninit},
pin::Pin,
},
};

// Aligned<T>
// *const T

impl<T: ?Sized> Destructure for Aligned<T> {
// SAFETY: Destructuring `*const T` is safe if and only if destructuring `T` with the same pattern
// is also safe.
unsafe impl<T> Destructure for *const T {
type Underlying = T;
type Test = T;

fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
**self as *mut T
*self as *mut T
}
}

unsafe impl<T: ?Sized, U: ?Sized> Restructure<&Aligned<T>> for U {
type Restructured = Aligned<Self>;
// SAFETY: `restructure` returns a valid `*const U` that upholds the same invariants as a mutably
// borrowed subfield of some `T`.
unsafe impl<T: ?Sized, U: ?Sized> Restructure<&*const T> for U {
type Restructured = *const U;

unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
// SAFETY: The caller has guaranteed that `ptr` is properly aligned.
unsafe { Aligned::new_unchecked(ptr as *const Self) }
ptr as *const Self
}
}

// AlignedMut<T>
// *mut T

impl<T: ?Sized> Destructure for AlignedMut<T> {
// SAFETY: Destructuring `*mut T` is safe if and only if destructuring `T` with the same pattern is
// also safe.
unsafe impl<T> Destructure for *mut T {
type Underlying = T;
type Test = T;

fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
**self
*self
}
}

unsafe impl<T: ?Sized, U: ?Sized> Restructure<&AlignedMut<T>> for U {
type Restructured = AlignedMut<Self>;
// SAFETY: `restructure` returns a valid `*mut U` that upholds the same invariants as a mutably
// borrowed subfield of some `T`.
unsafe impl<T: ?Sized, U: ?Sized> Restructure<&*mut T> for U {
type Restructured = *mut U;

unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
// SAFETY: The caller has guaranteed that `ptr` is properly aligned.
unsafe { AlignedMut::new_unchecked(ptr) }
ptr
}
}

// &MaybeUninit
// &MaybeUninit<T>

impl<'a, T> Destructure for &'a MaybeUninit<T> {
// SAFETY: Destructuring `&'a MaybeUninit<T>` is safe if and only if destructuring `&'a T` with the
// same pattern is also safe.
unsafe impl<'a, T> Destructure for &'a MaybeUninit<T> {
type Underlying = T;
type Test = &'a T;

fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
self.as_ptr() as *mut Self::Underlying
}
}

// SAFETY: `restructure` returns a valid `MaybeUninit` reference that upholds the same invariants as
// a mutably borrowed subfield of some `T`.
unsafe impl<'a: 'b, 'b, T, U: 'b> Restructure<&'b &'a MaybeUninit<T>> for U {
type Restructured = &'b MaybeUninit<U>;

Expand All @@ -65,16 +78,21 @@ unsafe impl<'a: 'b, 'b, T, U: 'b> Restructure<&'b &'a MaybeUninit<T>> for U {
}
}

// &mut MaybeUninit
// &mut MaybeUninit<T>

impl<'a, T> Destructure for &'a mut MaybeUninit<T> {
// SAFETY: Destructuring `&'a mut MaybeUninit<T>` is safe if and only if destructuring `&'a mut T`
// with the same pattern is also safe.
unsafe impl<'a, T> Destructure for &'a mut MaybeUninit<T> {
type Underlying = T;
type Test = &'a T;

fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
MaybeUninit::as_mut_ptr(self)
}
}

// SAFETY: `restructure` returns a valid `MaybeUninit` reference that upholds the same invariants as
// a mutably borrowed subfield of some `T`.
unsafe impl<'a: 'b, 'b, T, U: 'b> Restructure<&'b &'a mut MaybeUninit<T>> for U {
type Restructured = &'b mut MaybeUninit<U>;

Expand All @@ -87,56 +105,78 @@ unsafe impl<'a: 'b, 'b, T, U: 'b> Restructure<&'b &'a mut MaybeUninit<T>> for U

// &Cell<T>

impl<'a, T> Destructure for &'a Cell<T> {
// SAFETY: Destructuring `&'a Cell<T>` is safe if and only if destructuring `&'a T` with the same
// pattern is also safe.
unsafe impl<'a, T: ?Sized> Destructure for &'a Cell<T> {
type Underlying = T;
type Test = &'a T;

fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
self.as_ptr()
}
}

unsafe impl<'a: 'b, 'b, T, U: 'b> Restructure<&'b &'a Cell<T>> for U {
// SAFETY: `restructure` returns a valid `Cell` reference that upholds the same invariants as a
// mutably borrowed subfield of some `T`.
unsafe impl<'a: 'b, 'b, T: ?Sized, U: 'b + ?Sized> Restructure<&'b &'a Cell<T>> for U {
type Restructured = &'b Cell<U>;

unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
// SAFETY: The caller has guaranteed that `ptr` points to a subfield of some
// `&'b &'a Cell<T>`, so it's safe to dereference for the `'b` lifetime.
unsafe { &*ptr.cast() }
// `&'b &'a Cell<T>`, so it's safe to dereference for the `'b` lifetime. Additionally, `ptr`
// is guaranteed to have the same pointer metadata as a pointer to `Cell<U>`.
unsafe { &*::core::mem::transmute::<*mut Self, *const Cell<U>>(ptr) }
}
}

// &UnsafeCell<T>

impl<'a, T> Destructure for &'a UnsafeCell<T> {
// SAFETY: Destructuring `&'a UnsafeCell<T>` is safe if and only if destructuring `&'a T` with the
// same pattern is also safe.
unsafe impl<'a, T: ?Sized> Destructure for &'a UnsafeCell<T> {
type Underlying = T;
type Test = &'a T;

fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
self.get()
}
}

unsafe impl<'a: 'b, 'b, T, U: 'b> Restructure<&'b &'a UnsafeCell<T>> for U {
// SAFETY: `restructure` returns a valid `UnsafeCell` reference that upholds the same invariants as
// a mutably borrowed subfield of some `T`.
unsafe impl<'a: 'b, 'b, T: ?Sized, U: 'b + ?Sized> Restructure<&'b &'a UnsafeCell<T>> for U {
type Restructured = &'b UnsafeCell<U>;

unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
// SAFETY: The caller has guaranteed that `ptr` points to a subfield of some
// `&'b &'a UnsafeCell<T>`, so it's safe to dereference for the `'b` lifetime.
unsafe { &*ptr.cast() }
// `&'b &'a UnsafeCell<T>`, so it's safe to dereference for the `'b` lifetime. Additionally,
// `ptr` is guaranteed to have the same pointer metadata as a pointer to `UnsafeCell<U>`.
unsafe { &*::core::mem::transmute::<*mut Self, *const UnsafeCell<U>>(ptr) }
}
}

// Pin<&T> where T: StructuralPinning

impl<'a, T: StructuralPinning> Destructure for Pin<&'a T> {
// SAFETY: Destructuring `Pin<&'a T>` is safe if and only if destructuring `&'a T` with the same
// pattern is also safe.
unsafe impl<'a, T: StructuralPinning + ?Sized> Destructure for Pin<&'a T> {
type Underlying = T;
type Test = &'a T;

fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
// SAFETY: The value pointed to by `self` will continue to be treated as pinned.
unsafe { Pin::into_inner_unchecked(self.as_ref()) as *const T as *mut T }
}
}

unsafe impl<'a: 'b, 'b, T: StructuralPinning, U: 'b> Restructure<&'b Pin<&'a T>> for U {
// SAFETY: `restructure` returns a valid `Pin<&'a T>` that upholds the same invariants as a mutably
// borrowed subfield of some `T`.
unsafe impl<'a, 'b, T, U> Restructure<&'b Pin<&'a T>> for U
where
'a: 'b,
T: StructuralPinning + ?Sized,
U: 'b + ?Sized,
{
type Restructured = Pin<&'b U>;

unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
Expand All @@ -149,16 +189,26 @@ unsafe impl<'a: 'b, 'b, T: StructuralPinning, U: 'b> Restructure<&'b Pin<&'a T>>

// Pin<&mut T> where T: StructuralPinning

impl<'a, T: StructuralPinning> Destructure for Pin<&'a mut T> {
// SAFETY: Destructuring `Pin<&'a mut T>` is safe if and only if destructuring `&'a T` with the same
// pattern is also safe.
unsafe impl<'a, T: StructuralPinning + ?Sized> Destructure for Pin<&'a mut T> {
type Underlying = T;
type Test = &'a T;

fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
// SAFETY: The value pointed to by `self` will continue to be treated as pinned.
unsafe { Pin::into_inner_unchecked(self.as_mut()) as *mut T }
}
}

unsafe impl<'a: 'b, 'b, T: StructuralPinning, U: 'b> Restructure<&'b Pin<&'a mut T>> for U {
// SAFETY: `restructure` returns a valid `Pin<&'a mut T>` that upholds the same invariants as a
// mutably borrowed subfield of some `T`.
unsafe impl<'a, 'b, T, U> Restructure<&'b Pin<&'a mut T>> for U
where
'a: 'b,
T: StructuralPinning + ?Sized,
U: 'b + ?Sized,
{
type Restructured = Pin<&'b mut U>;

unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
Expand All @@ -171,14 +221,19 @@ unsafe impl<'a: 'b, 'b, T: StructuralPinning, U: 'b> Restructure<&'b Pin<&'a mut

// ManuallyDrop<T>

impl<'a, T> Destructure for ManuallyDrop<T> {
// SAFETY: Destructuring `ManuallyDrop<T>` is safe if and only if destructuring `T` with the same
// pattern is also safe.
unsafe impl<'a, T> Destructure for ManuallyDrop<T> {
type Underlying = T;
type Test = T;

fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
&mut **self as *mut Self::Underlying
}
}

// SAFETY: `restructure` returns a valid `ManuallyDrop<T>` that upholds the same invariants as a
// mutably borrowed subfield of some `T`.
unsafe impl<T, U> Restructure<&ManuallyDrop<T>> for U {
type Restructured = ManuallyDrop<U>;

Expand Down
Loading

0 comments on commit 3ab52ff

Please sign in to comment.