Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/pointer/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,22 @@ mod _transitions {
unsafe { Ptr::from_ptr(self) }
}

/// Checks the `Ptr`'s alignment at runtime, returning an aligned `Ptr`
/// on success.
pub(crate) fn bikeshed_try_into_aligned(
self,
) -> Option<Ptr<'a, T, (I::Aliasing, invariant::Aligned, I::Validity)>>
where
T: Sized,
{
if !crate::util::aligned_to::<_, T>(self.as_non_null()) {
return None;
}

// SAFETY: We just checked the alignment.
Some(unsafe { self.assume_alignment::<invariant::Aligned>() })
}

/// Recalls that `Ptr`'s referent is validly-aligned for `T`.
#[inline]
// TODO(#859): Reconsider the name of this method before making it
Expand Down
8 changes: 8 additions & 0 deletions src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use core::{
mem::{self, ManuallyDrop, MaybeUninit},
num::{NonZeroUsize, Wrapping},
ptr::NonNull,
};

use crate::{
Expand Down Expand Up @@ -280,6 +281,13 @@ impl<'a, T: ?Sized> AsAddress for &'a mut T {
}
}

impl<T: ?Sized> AsAddress for NonNull<T> {
#[inline(always)]
fn addr(self) -> usize {
AsAddress::addr(self.as_ptr())
}
}

impl<T: ?Sized> AsAddress for *const T {
#[inline(always)]
fn addr(self) -> usize {
Expand Down
30 changes: 6 additions & 24 deletions src/wrappers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,13 +142,8 @@ impl<T> Unalign<T> {
/// may prefer [`Deref::deref`], which is infallible.
#[inline(always)]
pub fn try_deref(&self) -> Option<&T> {
if !crate::util::aligned_to::<_, T>(self) {
return None;
}

// SAFETY: `deref_unchecked`'s safety requirement is that `self` is
// aligned to `align_of::<T>()`, which we just checked.
unsafe { Some(self.deref_unchecked()) }
let inner = Ptr::from_ref(self).transparent_wrapper_into_inner();
inner.bikeshed_try_into_aligned().map(Ptr::as_ref)
}

/// Attempts to return a mutable reference to the wrapped `T`, failing if
Expand All @@ -162,13 +157,8 @@ impl<T> Unalign<T> {
/// callers may prefer [`DerefMut::deref_mut`], which is infallible.
#[inline(always)]
pub fn try_deref_mut(&mut self) -> Option<&mut T> {
if !crate::util::aligned_to::<_, T>(&*self) {
return None;
}

// SAFETY: `deref_mut_unchecked`'s safety requirement is that `self` is
// aligned to `align_of::<T>()`, which we just checked.
unsafe { Some(self.deref_mut_unchecked()) }
let inner = Ptr::from_mut(self).transparent_wrapper_into_inner();
inner.bikeshed_try_into_aligned().map(Ptr::as_mut)
}

/// Returns a reference to the wrapped `T` without checking alignment.
Expand Down Expand Up @@ -334,22 +324,14 @@ impl<T: Unaligned> Deref for Unalign<T> {

#[inline(always)]
fn deref(&self) -> &T {
// SAFETY: `deref_unchecked`'s safety requirement is that `self` is
// aligned to `align_of::<T>()`. `T: Unaligned` guarantees that
// `align_of::<T>() == 1`, and all pointers are one-aligned because all
// addresses are divisible by 1.
unsafe { self.deref_unchecked() }
Ptr::from_ref(self).transparent_wrapper_into_inner().bikeshed_recall_aligned().as_ref()
}
}

impl<T: Unaligned> DerefMut for Unalign<T> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut T {
// SAFETY: `deref_mut_unchecked`'s safety requirement is that `self` is
// aligned to `align_of::<T>()`. `T: Unaligned` guarantees that
// `align_of::<T>() == 1`, and all pointers are one-aligned because all
// addresses are divisible by 1.
unsafe { self.deref_mut_unchecked() }
Ptr::from_mut(self).transparent_wrapper_into_inner().bikeshed_recall_aligned().as_mut()
}
}

Expand Down