Skip to content

Commit da96665

Browse files
committed
Less unsafe in dangling/without_provenance
1 parent 65a01a5 commit da96665

File tree

3 files changed

+19
-20
lines changed

3 files changed

+19
-20
lines changed

core/src/ptr/alignment.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,10 @@ impl Alignment {
4242
/// but in an `Alignment` instead of a `usize`.
4343
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
4444
#[inline]
45+
#[must_use]
4546
pub const fn of<T>() -> Self {
46-
// SAFETY: rustc ensures that type alignment is always a power of two.
47-
unsafe { Alignment::new_unchecked(mem::align_of::<T>()) }
47+
// This can't actually panic since type alignment is always a power of two.
48+
const { Alignment::new(mem::align_of::<T>()).unwrap() }
4849
}
4950

5051
/// Creates an `Alignment` from a `usize`, or returns `None` if it's
@@ -95,8 +96,13 @@ impl Alignment {
9596
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
9697
#[inline]
9798
pub const fn as_nonzero(self) -> NonZero<usize> {
99+
// This transmutes directly to avoid the UbCheck in `NonZero::new_unchecked`
100+
// since there's no way for the user to trip that check anyway -- the
101+
// validity invariant of the type would have to have been broken earlier --
102+
// and emitting it in an otherwise simple method is bad for compile time.
103+
98104
// SAFETY: All the discriminants are non-zero.
99-
unsafe { NonZero::new_unchecked(self.as_usize()) }
105+
unsafe { mem::transmute::<Alignment, NonZero<usize>>(self) }
100106
}
101107

102108
/// Returns the base-2 logarithm of the alignment.

core/src/ptr/mod.rs

+3-8
Original file line numberDiff line numberDiff line change
@@ -596,12 +596,7 @@ pub const fn null_mut<T: ?Sized + Thin>() -> *mut T {
596596
#[stable(feature = "strict_provenance", since = "1.84.0")]
597597
#[rustc_const_stable(feature = "strict_provenance", since = "1.84.0")]
598598
pub const fn without_provenance<T>(addr: usize) -> *const T {
599-
// An int-to-pointer transmute currently has exactly the intended semantics: it creates a
600-
// pointer without provenance. Note that this is *not* a stable guarantee about transmute
601-
// semantics, it relies on sysroot crates having special status.
602-
// SAFETY: every valid integer is also a valid pointer (as long as you don't dereference that
603-
// pointer).
604-
unsafe { mem::transmute(addr) }
599+
without_provenance_mut(addr)
605600
}
606601

607602
/// Creates a new pointer that is dangling, but non-null and well-aligned.
@@ -618,7 +613,7 @@ pub const fn without_provenance<T>(addr: usize) -> *const T {
618613
#[stable(feature = "strict_provenance", since = "1.84.0")]
619614
#[rustc_const_stable(feature = "strict_provenance", since = "1.84.0")]
620615
pub const fn dangling<T>() -> *const T {
621-
without_provenance(mem::align_of::<T>())
616+
dangling_mut()
622617
}
623618

624619
/// Creates a pointer with the given address and no [provenance][crate::ptr#provenance].
@@ -661,7 +656,7 @@ pub const fn without_provenance_mut<T>(addr: usize) -> *mut T {
661656
#[stable(feature = "strict_provenance", since = "1.84.0")]
662657
#[rustc_const_stable(feature = "strict_provenance", since = "1.84.0")]
663658
pub const fn dangling_mut<T>() -> *mut T {
664-
without_provenance_mut(mem::align_of::<T>())
659+
NonNull::dangling().as_ptr()
665660
}
666661

667662
/// Converts an address back to a pointer, picking up some previously 'exposed'

core/src/ptr/non_null.rs

+7-9
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,12 @@ impl<T: Sized> NonNull<T> {
9191
///
9292
/// This is a [Strict Provenance][crate::ptr#strict-provenance] API.
9393
#[unstable(feature = "nonnull_provenance", issue = "135243")]
94+
#[must_use]
95+
#[inline]
9496
pub const fn without_provenance(addr: NonZero<usize>) -> Self {
97+
let pointer = crate::ptr::without_provenance(addr.get());
9598
// SAFETY: we know `addr` is non-zero.
96-
unsafe {
97-
let ptr = crate::ptr::without_provenance_mut(addr.get());
98-
NonNull::new_unchecked(ptr)
99-
}
99+
unsafe { NonNull { pointer } }
100100
}
101101

102102
/// Creates a new `NonNull` that is dangling, but well-aligned.
@@ -123,11 +123,8 @@ impl<T: Sized> NonNull<T> {
123123
#[must_use]
124124
#[inline]
125125
pub const fn dangling() -> Self {
126-
// SAFETY: ptr::dangling_mut() returns a non-null well-aligned pointer.
127-
unsafe {
128-
let ptr = crate::ptr::dangling_mut::<T>();
129-
NonNull::new_unchecked(ptr)
130-
}
126+
let align = crate::ptr::Alignment::of::<T>();
127+
NonNull::without_provenance(align.as_nonzero())
131128
}
132129

133130
/// Converts an address back to a mutable pointer, picking up some previously 'exposed'
@@ -137,6 +134,7 @@ impl<T: Sized> NonNull<T> {
137134
///
138135
/// This is an [Exposed Provenance][crate::ptr#exposed-provenance] API.
139136
#[unstable(feature = "nonnull_provenance", issue = "135243")]
137+
#[inline]
140138
pub fn with_exposed_provenance(addr: NonZero<usize>) -> Self {
141139
// SAFETY: we know `addr` is non-zero.
142140
unsafe {

0 commit comments

Comments
 (0)