about summary refs log tree commit diff
path: root/library/core/src
diff options
context:
space:
mode:
authorScott McMurray <scottmcm@users.noreply.github.com>2025-01-10 13:00:45 -0800
committerScott McMurray <scottmcm@users.noreply.github.com>2025-01-15 22:17:57 -0800
commitc18718c9c28cc4c700312775c2b7f87cd79d3063 (patch)
tree7a2b8e3faab3a4a953a2f6af19c7afe6d27f2397 /library/core/src
parent5cd16b7f2bc3624f2d658aa87151279878d2652a (diff)
downloadrust-c18718c9c28cc4c700312775c2b7f87cd79d3063.tar.gz
rust-c18718c9c28cc4c700312775c2b7f87cd79d3063.zip
Less unsafe in `dangling`/`without_provenance`
Diffstat (limited to 'library/core/src')
-rw-r--r--library/core/src/ptr/alignment.rs12
-rw-r--r--library/core/src/ptr/mod.rs11
-rw-r--r--library/core/src/ptr/non_null.rs16
3 files changed, 19 insertions, 20 deletions
diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs
index 74a1d40f4e7..2da94e72566 100644
--- a/library/core/src/ptr/alignment.rs
+++ b/library/core/src/ptr/alignment.rs
@@ -42,9 +42,10 @@ impl Alignment {
     /// but in an `Alignment` instead of a `usize`.
     #[unstable(feature = "ptr_alignment_type", issue = "102070")]
     #[inline]
+    #[must_use]
     pub const fn of<T>() -> Self {
-        // SAFETY: rustc ensures that type alignment is always a power of two.
-        unsafe { Alignment::new_unchecked(mem::align_of::<T>()) }
+        // This can't actually panic since type alignment is always a power of two.
+        const { Alignment::new(mem::align_of::<T>()).unwrap() }
     }
 
     /// Creates an `Alignment` from a `usize`, or returns `None` if it's
@@ -95,8 +96,13 @@ impl Alignment {
     #[unstable(feature = "ptr_alignment_type", issue = "102070")]
     #[inline]
     pub const fn as_nonzero(self) -> NonZero<usize> {
+        // This transmutes directly to avoid the UbCheck in `NonZero::new_unchecked`
+        // since there's no way for the user to trip that check anyway -- the
+        // validity invariant of the type would have to have been broken earlier --
+        // and emitting it in an otherwise simple method is bad for compile time.
+
         // SAFETY: All the discriminants are non-zero.
-        unsafe { NonZero::new_unchecked(self.as_usize()) }
+        unsafe { mem::transmute::<Alignment, NonZero<usize>>(self) }
     }
 
     /// Returns the base-2 logarithm of the alignment.
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index f58c0e12411..e1348552b65 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -596,12 +596,7 @@ pub const fn null_mut<T: ?Sized + Thin>() -> *mut T {
 #[stable(feature = "strict_provenance", since = "1.84.0")]
 #[rustc_const_stable(feature = "strict_provenance", since = "1.84.0")]
 pub const fn without_provenance<T>(addr: usize) -> *const T {
-    // An int-to-pointer transmute currently has exactly the intended semantics: it creates a
-    // pointer without provenance. Note that this is *not* a stable guarantee about transmute
-    // semantics, it relies on sysroot crates having special status.
-    // SAFETY: every valid integer is also a valid pointer (as long as you don't dereference that
-    // pointer).
-    unsafe { mem::transmute(addr) }
+    without_provenance_mut(addr)
 }
 
 /// 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 {
 #[stable(feature = "strict_provenance", since = "1.84.0")]
 #[rustc_const_stable(feature = "strict_provenance", since = "1.84.0")]
 pub const fn dangling<T>() -> *const T {
-    without_provenance(mem::align_of::<T>())
+    dangling_mut()
 }
 
 /// 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 {
 #[stable(feature = "strict_provenance", since = "1.84.0")]
 #[rustc_const_stable(feature = "strict_provenance", since = "1.84.0")]
 pub const fn dangling_mut<T>() -> *mut T {
-    without_provenance_mut(mem::align_of::<T>())
+    NonNull::dangling().as_ptr()
 }
 
 /// Converts an address back to a pointer, picking up some previously 'exposed'
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index 2c9131254f7..d93069d384e 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -91,12 +91,12 @@ impl<T: Sized> NonNull<T> {
     ///
     /// This is a [Strict Provenance][crate::ptr#strict-provenance] API.
     #[unstable(feature = "nonnull_provenance", issue = "135243")]
+    #[must_use]
+    #[inline]
     pub const fn without_provenance(addr: NonZero<usize>) -> Self {
+        let pointer = crate::ptr::without_provenance(addr.get());
         // SAFETY: we know `addr` is non-zero.
-        unsafe {
-            let ptr = crate::ptr::without_provenance_mut(addr.get());
-            NonNull::new_unchecked(ptr)
-        }
+        unsafe { NonNull { pointer } }
     }
 
     /// Creates a new `NonNull` that is dangling, but well-aligned.
@@ -123,11 +123,8 @@ impl<T: Sized> NonNull<T> {
     #[must_use]
     #[inline]
     pub const fn dangling() -> Self {
-        // SAFETY: ptr::dangling_mut() returns a non-null well-aligned pointer.
-        unsafe {
-            let ptr = crate::ptr::dangling_mut::<T>();
-            NonNull::new_unchecked(ptr)
-        }
+        let align = crate::ptr::Alignment::of::<T>();
+        NonNull::without_provenance(align.as_nonzero())
     }
 
     /// Converts an address back to a mutable pointer, picking up some previously 'exposed'
@@ -137,6 +134,7 @@ impl<T: Sized> NonNull<T> {
     ///
     /// This is an [Exposed Provenance][crate::ptr#exposed-provenance] API.
     #[unstable(feature = "nonnull_provenance", issue = "135243")]
+    #[inline]
     pub fn with_exposed_provenance(addr: NonZero<usize>) -> Self {
         // SAFETY: we know `addr` is non-zero.
         unsafe {