]> git.lizzy.rs Git - rust.git/commitdiff
Add `as_uninit`-like methods to pointer types and unify documentation of `as_ref...
authorTim Diekmann <tim.diekmann@3dvision.de>
Mon, 17 Aug 2020 12:22:59 +0000 (14:22 +0200)
committerTim Diekmann <tim.diekmann@3dvision.de>
Mon, 17 Aug 2020 12:23:14 +0000 (14:23 +0200)
Fix example in `NonNull::as_uninit_slice`

Rename feature gate to "ptr_as_uninit"

Make methods more consistent with already stable methods

Make `pointer::as_uninit_slice` return an `Option`

Fix placement for `// SAFETY` section

Add `as_uninit_ref` and `as_uninit_mut` to pointers

Fix doctest

Update tracking issue

Fix doc links

Apply suggestions from review

Make wording about counterparts consistent

Fix doc links

Improve documentation

Fix doc-tests

Fix doc links ... again

Apply suggestions from review

Apply suggestions from Review

Apply suggestion from review to all affected files

Add missing words in safety sections in `as_uninit_slice_mut`

Fix safety-comment in `NonNull::as_uninit_slice_mut`

library/core/src/lib.rs
library/core/src/ptr/const_ptr.rs
library/core/src/ptr/mut_ptr.rs
library/core/src/ptr/non_null.rs

index fcf5454308b475a73a412bc720bddc4e905d3892..26568cdcf9beecf33f9faed53c9e2c26b139f409 100644 (file)
 #![feature(optin_builtin_traits)]
 #![feature(or_patterns)]
 #![feature(prelude_import)]
+#![feature(ptr_as_uninit)]
 #![feature(repr_simd, platform_intrinsics)]
 #![feature(rustc_attrs)]
 #![feature(simd_ffi)]
index a16970e9fd1802863411b74ac32da08acf1a24b2..493cfe4992b6da15b33882780deb9e49025af2a1 100644 (file)
@@ -2,7 +2,7 @@
 use crate::cmp::Ordering::{self, Equal, Greater, Less};
 use crate::intrinsics;
 use crate::mem;
-use crate::slice::SliceIndex;
+use crate::slice::{self, SliceIndex};
 
 #[lang = "const_ptr"]
 impl<T: ?Sized> *const T {
@@ -38,32 +38,33 @@ pub const fn cast<U>(self) -> *const U {
         self as _
     }
 
-    /// Returns `None` if the pointer is null, or else returns a reference to
-    /// the value wrapped in `Some`.
+    /// Returns `None` if the pointer is null, or else returns a shared reference to
+    /// the value wrapped in `Some`. If the value may be uninitialized, [`as_uninit_ref`]
+    /// must be used instead.
     ///
-    /// # Safety
+    /// [`as_uninit_ref`]: #method.as_uninit_ref
     ///
-    /// While this method and its mutable counterpart are useful for
-    /// null-safety, it is important to note that this is still an unsafe
-    /// operation because the returned value could be pointing to invalid
-    /// memory.
+    /// # Safety
     ///
     /// When calling this method, you have to ensure that *either* the pointer is NULL *or*
     /// all of the following is true:
-    /// - it is properly aligned
-    /// - it must point to an initialized instance of T; in particular, the pointer must be
-    ///   "dereferenceable" in the sense defined [here].
+    ///
+    /// * The pointer must be properly aligned.
+    ///
+    /// * It must be "dereferencable" in the sense defined in [the module documentation].
+    ///
+    /// * The pointer must point to an initialized instance of `T`.
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get mutated (except inside `UnsafeCell`).
     ///
     /// This applies even if the result of this method is unused!
     /// (The part about being initialized is not yet fully decided, but until
     /// it is, the only safe approach is to ensure that they are indeed initialized.)
     ///
-    /// Additionally, the lifetime `'a` returned is arbitrarily chosen and does
-    /// not necessarily reflect the actual lifetime of the data. *You* must enforce
-    /// Rust's aliasing rules. In particular, for the duration of this lifetime,
-    /// the memory the pointer points to must not get mutated (except inside `UnsafeCell`).
-    ///
-    /// [here]: crate::ptr#safety
+    /// [the module documentation]: crate::ptr#safety
     ///
     /// # Examples
     ///
@@ -101,6 +102,56 @@ pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
         if self.is_null() { None } else { unsafe { Some(&*self) } }
     }
 
+    /// Returns `None` if the pointer is null, or else returns a shared reference to
+    /// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require
+    /// that the value has to be initialized.
+    ///
+    /// [`as_ref`]: #method.as_ref
+    ///
+    /// # Safety
+    ///
+    /// When calling this method, you have to ensure that *either* the pointer is NULL *or*
+    /// all of the following is true:
+    ///
+    /// * The pointer must be properly aligned.
+    ///
+    /// * It must be "dereferencable" in the sense defined in [the module documentation].
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get mutated (except inside `UnsafeCell`).
+    ///
+    /// This applies even if the result of this method is unused!
+    ///
+    /// [the module documentation]: crate::ptr#safety
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(ptr_as_uninit)]
+    ///
+    /// let ptr: *const u8 = &10u8 as *const u8;
+    ///
+    /// unsafe {
+    ///     if let Some(val_back) = ptr.as_uninit_ref() {
+    ///         println!("We got back the value: {}!", val_back.assume_init());
+    ///     }
+    /// }
+    /// ```
+    #[inline]
+    #[unstable(feature = "ptr_as_uninit", issue = "75402")]
+    pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
+    where
+        T: Sized,
+    {
+        // SAFETY: the caller must guarantee that `self` meets all the
+        // requirements for a reference.
+        if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit<T>) }) }
+    }
+
     /// Calculates the offset from a pointer.
     ///
     /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
@@ -906,6 +957,55 @@ pub unsafe fn get_unchecked<I>(self, index: I) -> *const I::Output
         // SAFETY: the caller ensures that `self` is dereferencable and `index` in-bounds.
         unsafe { index.get_unchecked(self) }
     }
+
+    /// Returns `None` if the pointer is null, or else returns a shared slice to
+    /// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require
+    /// that the value has to be initialized.
+    ///
+    /// [`as_ref`]: #method.as_ref
+    ///
+    /// # Safety
+    ///
+    /// When calling this method, you have to ensure that *either* the pointer is NULL *or*
+    /// all of the following is true:
+    ///
+    /// * The pointer must be [valid] for reads for `ptr.len() * mem::size_of::<T>()` many bytes,
+    ///   and it must be properly aligned. This means in particular:
+    ///
+    ///     * The entire memory range of this slice must be contained within a single allocated object!
+    ///       Slices can never span across multiple allocated objects.
+    ///
+    ///     * The pointer must be aligned even for zero-length slices. One
+    ///       reason for this is that enum layout optimizations may rely on references
+    ///       (including slices of any length) being aligned and non-null to distinguish
+    ///       them from other data. You can obtain a pointer that is usable as `data`
+    ///       for zero-length slices using [`NonNull::dangling()`].
+    ///
+    /// * The total size `ptr.len() * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`.
+    ///   See the safety documentation of [`pointer::offset`].
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get mutated (except inside `UnsafeCell`).
+    ///
+    /// This applies even if the result of this method is unused!
+    ///
+    /// See also [`slice::from_raw_parts`][].
+    ///
+    /// [valid]: crate::ptr#safety
+    /// [`NonNull::dangling()`]: NonNull::dangling
+    /// [`pointer::offset`]: ../std/primitive.pointer.html#method.offset
+    #[inline]
+    #[unstable(feature = "ptr_as_uninit", issue = "75402")]
+    pub unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> {
+        if self.is_null() {
+            None
+        } else {
+            // SAFETY: the caller must uphold the safety contract for `as_uninit_slice`.
+            Some(unsafe { slice::from_raw_parts(self as *const MaybeUninit<T>, self.len()) })
+        }
+    }
 }
 
 // Equality for pointers
index b47f90c59962926462cd306ac87baf8d4f05f580..eeb425de262be96a43649d93f29abfae80029308 100644 (file)
@@ -1,7 +1,7 @@
 use super::*;
 use crate::cmp::Ordering::{self, Equal, Greater, Less};
 use crate::intrinsics;
-use crate::slice::SliceIndex;
+use crate::slice::{self, SliceIndex};
 
 #[lang = "mut_ptr"]
 impl<T: ?Sized> *mut T {
@@ -37,32 +37,36 @@ pub const fn cast<U>(self) -> *mut U {
         self as _
     }
 
-    /// Returns `None` if the pointer is null, or else returns a reference to
-    /// the value wrapped in `Some`.
+    /// Returns `None` if the pointer is null, or else returns a shared reference to
+    /// the value wrapped in `Some`. If the value may be uninitialized, [`as_uninit_ref`]
+    /// must be used instead.
     ///
-    /// # Safety
+    /// For the mutable counterpart see [`as_mut`].
+    ///
+    /// [`as_uninit_ref`]: #method.as_uninit_ref-1
+    /// [`as_mut`]: #method.as_mut
     ///
-    /// While this method and its mutable counterpart are useful for
-    /// null-safety, it is important to note that this is still an unsafe
-    /// operation because the returned value could be pointing to invalid
-    /// memory.
+    /// # Safety
     ///
     /// When calling this method, you have to ensure that *either* the pointer is NULL *or*
     /// all of the following is true:
-    /// - it is properly aligned
-    /// - it must point to an initialized instance of T; in particular, the pointer must be
-    ///   "dereferencable" in the sense defined [here].
+    ///
+    /// * The pointer must be properly aligned.
+    ///
+    /// * It must be "dereferencable" in the sense defined in [the module documentation].
+    ///
+    /// * The pointer must point to an initialized instance of `T`.
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get mutated (except inside `UnsafeCell`).
     ///
     /// This applies even if the result of this method is unused!
     /// (The part about being initialized is not yet fully decided, but until
     /// it is, the only safe approach is to ensure that they are indeed initialized.)
     ///
-    /// Additionally, the lifetime `'a` returned is arbitrarily chosen and does
-    /// not necessarily reflect the actual lifetime of the data. *You* must enforce
-    /// Rust's aliasing rules. In particular, for the duration of this lifetime,
-    /// the memory the pointer points to must not get mutated (except inside `UnsafeCell`).
-    ///
-    /// [here]: crate::ptr#safety
+    /// [the module documentation]: crate::ptr#safety
     ///
     /// # Examples
     ///
@@ -100,6 +104,59 @@ pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
         if self.is_null() { None } else { unsafe { Some(&*self) } }
     }
 
+    /// Returns `None` if the pointer is null, or else returns a shared reference to
+    /// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require
+    /// that the value has to be initialized.
+    ///
+    /// For the mutable counterpart see [`as_uninit_mut`].
+    ///
+    /// [`as_ref`]: #method.as_ref-1
+    /// [`as_uninit_mut`]: #method.as_uninit_mut
+    ///
+    /// # Safety
+    ///
+    /// When calling this method, you have to ensure that *either* the pointer is NULL *or*
+    /// all of the following is true:
+    ///
+    /// * The pointer must be properly aligned.
+    ///
+    /// * It must be "dereferencable" in the sense defined in [the module documentation].
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get mutated (except inside `UnsafeCell`).
+    ///
+    /// This applies even if the result of this method is unused!
+    ///
+    /// [the module documentation]: crate::ptr#safety
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(ptr_as_uninit)]
+    ///
+    /// let ptr: *mut u8 = &mut 10u8 as *mut u8;
+    ///
+    /// unsafe {
+    ///     if let Some(val_back) = ptr.as_uninit_ref() {
+    ///         println!("We got back the value: {}!", val_back.assume_init());
+    ///     }
+    /// }
+    /// ```
+    #[inline]
+    #[unstable(feature = "ptr_as_uninit", issue = "75402")]
+    pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
+    where
+        T: Sized,
+    {
+        // SAFETY: the caller must guarantee that `self` meets all the
+        // requirements for a reference.
+        if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit<T>) }) }
+    }
+
     /// Calculates the offset from a pointer.
     ///
     /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
@@ -225,33 +282,36 @@ pub const fn wrapping_offset(self, count: isize) -> *mut T
         unsafe { intrinsics::arith_offset(self, count) as *mut T }
     }
 
-    /// Returns `None` if the pointer is null, or else returns a mutable
-    /// reference to the value wrapped in `Some`.
+    /// Returns `None` if the pointer is null, or else returns a unique reference to
+    /// the value wrapped in `Some`. If the value may be uninitialized, [`as_uninit_mut`]
+    /// must be used instead.
     ///
-    /// # Safety
+    /// For the shared counterpart see [`as_ref`].
     ///
-    /// As with [`as_ref`], this is unsafe because it cannot verify the validity
-    /// of the returned pointer, nor can it ensure that the lifetime `'a`
-    /// returned is indeed a valid lifetime for the contained data.
+    /// [`as_uninit_mut`]: #method.as_uninit_mut
+    /// [`as_ref`]: #method.as_ref-1
+    ///
+    /// # Safety
     ///
     /// When calling this method, you have to ensure that *either* the pointer is NULL *or*
     /// all of the following is true:
-    /// - it is properly aligned
-    /// - it must point to an initialized instance of T; in particular, the pointer must be
-    ///   "dereferenceable" in the sense defined [here].
+    ///
+    /// * The pointer must be properly aligned.
+    ///
+    /// * It must be "dereferencable" in the sense defined in [the module documentation].
+    ///
+    /// * The pointer must point to an initialized instance of `T`.
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get accessed (read or written) through any other pointer.
     ///
     /// This applies even if the result of this method is unused!
     /// (The part about being initialized is not yet fully decided, but until
-    /// it is the only safe approach is to ensure that they are indeed initialized.)
-    ///
-    /// Additionally, the lifetime `'a` returned is arbitrarily chosen and does
-    /// not necessarily reflect the actual lifetime of the data. *You* must enforce
-    /// Rust's aliasing rules. In particular, for the duration of this lifetime,
-    /// the memory this pointer points to must not get accessed (read or written)
-    /// through any other pointer.
+    /// it is, the only safe approach is to ensure that they are indeed initialized.)
     ///
-    /// [here]: crate::ptr#safety
-    /// [`as_ref`]: #method.as_ref
+    /// [the module documentation]: crate::ptr#safety
     ///
     /// # Examples
     ///
@@ -262,6 +322,7 @@ pub const fn wrapping_offset(self, count: isize) -> *mut T
     /// let ptr: *mut u32 = s.as_mut_ptr();
     /// let first_value = unsafe { ptr.as_mut().unwrap() };
     /// *first_value = 4;
+    /// # assert_eq!(s, [4, 2, 3]);
     /// println!("{:?}", s); // It'll print: "[4, 2, 3]".
     /// ```
     ///
@@ -276,6 +337,7 @@ pub const fn wrapping_offset(self, count: isize) -> *mut T
     /// let ptr: *mut u32 = s.as_mut_ptr();
     /// let first_value = unsafe { &mut *ptr };
     /// *first_value = 4;
+    /// # assert_eq!(s, [4, 2, 3]);
     /// println!("{:?}", s); // It'll print: "[4, 2, 3]".
     /// ```
     #[stable(feature = "ptr_as_ref", since = "1.9.0")]
@@ -286,6 +348,43 @@ pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> {
         if self.is_null() { None } else { unsafe { Some(&mut *self) } }
     }
 
+    /// Returns `None` if the pointer is null, or else returns a unique reference to
+    /// the value wrapped in `Some`. In contrast to [`as_mut`], this does not require
+    /// that the value has to be initialized.
+    ///
+    /// For the shared counterpart see [`as_uninit_ref`].
+    ///
+    /// [`as_mut`]: #method.as_mut
+    /// [`as_uninit_ref`]: #method.as_uninit_ref-1
+    ///
+    /// # Safety
+    ///
+    /// When calling this method, you have to ensure that *either* the pointer is NULL *or*
+    /// all of the following is true:
+    ///
+    /// * The pointer must be properly aligned.
+    ///
+    /// * It must be "dereferencable" in the sense defined in [the module documentation].
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get accessed (read or written) through any other pointer.
+    ///
+    /// This applies even if the result of this method is unused!
+    ///
+    /// [the module documentation]: crate::ptr#safety
+    #[inline]
+    #[unstable(feature = "ptr_as_uninit", issue = "75402")]
+    pub unsafe fn as_uninit_mut<'a>(self) -> Option<&'a mut MaybeUninit<T>>
+    where
+        T: Sized,
+    {
+        // SAFETY: the caller must guarantee that `self` meets all the
+        // requirements for a reference.
+        if self.is_null() { None } else { Some(unsafe { &mut *(self as *mut MaybeUninit<T>) }) }
+    }
+
     /// Returns whether two pointers are guaranteed to be equal.
     ///
     /// At runtime this function behaves like `self == other`.
@@ -1112,6 +1211,110 @@ pub unsafe fn get_unchecked_mut<I>(self, index: I) -> *mut I::Output
         // SAFETY: the caller ensures that `self` is dereferencable and `index` in-bounds.
         unsafe { index.get_unchecked_mut(self) }
     }
+
+    /// Returns `None` if the pointer is null, or else returns a shared slice to
+    /// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require
+    /// that the value has to be initialized.
+    ///
+    /// For the mutable counterpart see [`as_uninit_slice_mut`].
+    ///
+    /// [`as_ref`]: #method.as_ref-1
+    /// [`as_uninit_slice_mut`]: #method.as_uninit_slice_mut
+    ///
+    /// # Safety
+    ///
+    /// When calling this method, you have to ensure that *either* the pointer is NULL *or*
+    /// all of the following is true:
+    ///
+    /// * The pointer must be [valid] for reads for `ptr.len() * mem::size_of::<T>()` many bytes,
+    ///   and it must be properly aligned. This means in particular:
+    ///
+    ///     * The entire memory range of this slice must be contained within a single allocated object!
+    ///       Slices can never span across multiple allocated objects.
+    ///
+    ///     * The pointer must be aligned even for zero-length slices. One
+    ///       reason for this is that enum layout optimizations may rely on references
+    ///       (including slices of any length) being aligned and non-null to distinguish
+    ///       them from other data. You can obtain a pointer that is usable as `data`
+    ///       for zero-length slices using [`NonNull::dangling()`].
+    ///
+    /// * The total size `ptr.len() * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`.
+    ///   See the safety documentation of [`pointer::offset`].
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get mutated (except inside `UnsafeCell`).
+    ///
+    /// This applies even if the result of this method is unused!
+    ///
+    /// See also [`slice::from_raw_parts`][].
+    ///
+    /// [valid]: crate::ptr#safety
+    /// [`NonNull::dangling()`]: NonNull::dangling
+    /// [`pointer::offset`]: ../std/primitive.pointer.html#method.offset
+    #[inline]
+    #[unstable(feature = "ptr_as_uninit", issue = "75402")]
+    pub unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> {
+        if self.is_null() {
+            None
+        } else {
+            // SAFETY: the caller must uphold the safety contract for `as_uninit_slice`.
+            Some(unsafe { slice::from_raw_parts(self as *const MaybeUninit<T>, self.len()) })
+        }
+    }
+
+    /// Returns `None` if the pointer is null, or else returns a unique slice to
+    /// the value wrapped in `Some`. In contrast to [`as_mut`], this does not require
+    /// that the value has to be initialized.
+    ///
+    /// For the shared counterpart see [`as_uninit_slice`].
+    ///
+    /// [`as_mut`]: #method.as_mut
+    /// [`as_uninit_slice`]: #method.as_uninit_slice-1
+    ///
+    /// # Safety
+    ///
+    /// When calling this method, you have to ensure that *either* the pointer is NULL *or*
+    /// all of the following is true:
+    ///
+    /// * The pointer must be [valid] for reads and writes for `ptr.len() * mem::size_of::<T>()`
+    ///   many bytes, and it must be properly aligned. This means in particular:
+    ///
+    ///     * The entire memory range of this slice must be contained within a single allocated object!
+    ///       Slices can never span across multiple allocated objects.
+    ///
+    ///     * The pointer must be aligned even for zero-length slices. One
+    ///       reason for this is that enum layout optimizations may rely on references
+    ///       (including slices of any length) being aligned and non-null to distinguish
+    ///       them from other data. You can obtain a pointer that is usable as `data`
+    ///       for zero-length slices using [`NonNull::dangling()`].
+    ///
+    /// * The total size `ptr.len() * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`.
+    ///   See the safety documentation of [`pointer::offset`].
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get accessed (read or written) through any other pointer.
+    ///
+    /// This applies even if the result of this method is unused!
+    ///
+    /// See also [`slice::from_raw_parts_mut`][].
+    ///
+    /// [valid]: crate::ptr#safety
+    /// [`NonNull::dangling()`]: NonNull::dangling
+    /// [`pointer::offset`]: ../std/primitive.pointer.html#method.offset
+    #[inline]
+    #[unstable(feature = "ptr_as_uninit", issue = "75402")]
+    pub unsafe fn as_uninit_slice_mut<'a>(self) -> Option<&'a mut [MaybeUninit<T>]> {
+        if self.is_null() {
+            None
+        } else {
+            // SAFETY: the caller must uphold the safety contract for `as_uninit_slice_mut`.
+            Some(unsafe { slice::from_raw_parts_mut(self as *mut MaybeUninit<T>, self.len()) })
+        }
+    }
 }
 
 // Equality for pointers
index d876ab23653f367925b8f904ad1891705a080356..294a3173d0cbf7ee00a4a0b18c197339ca6cdc3c 100644 (file)
@@ -3,10 +3,10 @@
 use crate::fmt;
 use crate::hash;
 use crate::marker::Unsize;
-use crate::mem;
+use crate::mem::{self, MaybeUninit};
 use crate::ops::{CoerceUnsized, DispatchFromDyn};
 use crate::ptr::Unique;
-use crate::slice::SliceIndex;
+use crate::slice::{self, SliceIndex};
 
 /// `*mut T` but non-zero and covariant.
 ///
@@ -76,6 +76,70 @@ pub const fn dangling() -> Self {
             NonNull::new_unchecked(ptr)
         }
     }
+
+    /// Returns a shared references to the value. In contrast to [`as_ref`], this does not require
+    /// that the value has to be initialized.
+    ///
+    /// For the mutable counterpart see [`as_uninit_mut`].
+    ///
+    /// [`as_ref`]: #method.as_ref
+    /// [`as_uninit_mut`]: #method.as_uninit_mut
+    ///
+    /// # Safety
+    ///
+    /// When calling this method, you have to ensure that all of the following is true:
+    ///
+    /// * The pointer must be properly aligned.
+    ///
+    /// * It must be "dereferencable" in the sense defined in [the module documentation].
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get mutated (except inside `UnsafeCell`).
+    ///
+    /// This applies even if the result of this method is unused!
+    ///
+    /// [the module documentation]: crate::ptr#safety
+    #[inline]
+    #[unstable(feature = "ptr_as_uninit", issue = "75402")]
+    pub unsafe fn as_uninit_ref(&self) -> &MaybeUninit<T> {
+        // SAFETY: the caller must guarantee that `self` meets all the
+        // requirements for a reference.
+        unsafe { &*self.cast().as_ptr() }
+    }
+
+    /// Returns a unique references to the value. In contrast to [`as_mut`], this does not require
+    /// that the value has to be initialized.
+    ///
+    /// For the shared counterpart see [`as_uninit_ref`].
+    ///
+    /// [`as_mut`]: #method.as_mut
+    /// [`as_uninit_ref`]: #method.as_uninit_ref
+    ///
+    /// # Safety
+    ///
+    /// When calling this method, you have to ensure that all of the following is true:
+    ///
+    /// * The pointer must be properly aligned.
+    ///
+    /// * It must be "dereferencable" in the sense defined in [the module documentation].
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get accessed (read or written) through any other pointer.
+    ///
+    /// This applies even if the result of this method is unused!
+    ///
+    /// [the module documentation]: crate::ptr#safety
+    #[inline]
+    #[unstable(feature = "ptr_as_uninit", issue = "75402")]
+    pub unsafe fn as_uninit_mut(&mut self) -> &mut MaybeUninit<T> {
+        // SAFETY: the caller must guarantee that `self` meets all the
+        // requirements for a reference.
+        unsafe { &mut *self.cast().as_ptr() }
+    }
 }
 
 impl<T: ?Sized> NonNull<T> {
@@ -112,29 +176,34 @@ pub const fn as_ptr(self) -> *mut T {
         self.pointer as *mut T
     }
 
-    /// Dereferences the content.
+    /// Returns a shared reference to the value. If the value may be uninitialized, [`as_uninit_ref`]
+    /// must be used instead.
+    ///
+    /// For the mutable counterpart see [`as_mut`].
     ///
-    /// The resulting lifetime is bound to self so this behaves "as if"
-    /// it were actually an instance of T that is getting borrowed. If a longer
-    /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`.
+    /// [`as_uninit_ref`]: #method.as_uninit_ref
+    /// [`as_mut`]: #method.as_mut
     ///
     /// # Safety
     ///
     /// When calling this method, you have to ensure that all of the following is true:
-    /// - `self` is properly aligned
-    /// - `self` must point to an initialized instance of T; in particular, the pointer must be
-    ///   "dereferencable" in the sense defined [here].
+    ///
+    /// * The pointer must be properly aligned.
+    ///
+    /// * It must be "dereferencable" in the sense defined in [the module documentation].
+    ///
+    /// * The pointer must point to an initialized instance of `T`.
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get mutated (except inside `UnsafeCell`).
     ///
     /// This applies even if the result of this method is unused!
     /// (The part about being initialized is not yet fully decided, but until
     /// it is, the only safe approach is to ensure that they are indeed initialized.)
     ///
-    /// Additionally, the lifetime of `self` does not necessarily reflect the actual
-    /// lifetime of the data. *You* must enforce Rust's aliasing rules. In particular,
-    /// for the duration of this lifetime, the memory the pointer points to must not
-    /// get mutated (except inside `UnsafeCell`).
-    ///
-    /// [here]: crate::ptr#safety
+    /// [the module documentation]: crate::ptr#safety
     #[stable(feature = "nonnull", since = "1.25.0")]
     #[inline]
     pub unsafe fn as_ref(&self) -> &T {
@@ -143,29 +212,34 @@ pub unsafe fn as_ref(&self) -> &T {
         unsafe { &*self.as_ptr() }
     }
 
-    /// Mutably dereferences the content.
+    /// Returns a unique reference to the value. If the value may be uninitialized, [`as_uninit_mut`]
+    /// must be used instead.
+    ///
+    /// For the shared counterpart see [`as_ref`].
     ///
-    /// The resulting lifetime is bound to self so this behaves "as if"
-    /// it were actually an instance of T that is getting borrowed. If a longer
-    /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`.
+    /// [`as_uninit_mut`]: #method.as_uninit_mut
+    /// [`as_ref`]: #method.as_ref
     ///
     /// # Safety
     ///
     /// When calling this method, you have to ensure that all of the following is true:
-    /// - `self` is properly aligned
-    /// - `self` must point to an initialized instance of T; in particular, the pointer must be
-    ///   "dereferenceable" in the sense defined [here].
+    ///
+    /// * The pointer must be properly aligned.
+    ///
+    /// * It must be "dereferencable" in the sense defined in [the module documentation].
+    ///
+    /// * The pointer must point to an initialized instance of `T`.
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get accessed (read or written) through any other pointer.
     ///
     /// This applies even if the result of this method is unused!
     /// (The part about being initialized is not yet fully decided, but until
-    /// it is the only safe approach is to ensure that they are indeed initialized.)
-    ///
-    /// Additionally, the lifetime of `self` does not necessarily reflect the actual
-    /// lifetime of the data. *You* must enforce Rust's aliasing rules. In particular,
-    /// for the duration of this lifetime, the memory this pointer points to must not
-    /// get accessed (read or written) through any other pointer.
+    /// it is, the only safe approach is to ensure that they are indeed initialized.)
     ///
-    /// [here]: crate::ptr#safety
+    /// [the module documentation]: crate::ptr#safety
     #[stable(feature = "nonnull", since = "1.25.0")]
     #[inline]
     pub unsafe fn as_mut(&mut self) -> &mut T {
@@ -278,6 +352,115 @@ pub const fn as_mut_ptr(self) -> *mut T {
         self.as_non_null_ptr().as_ptr()
     }
 
+    /// Returns a shared reference to a slice of possibly uninitialized values. In contrast to
+    /// [`as_ref`], this does not require that the value has to be initialized.
+    ///
+    /// For the mutable counterpart see [`as_uninit_slice_mut`].
+    ///
+    /// [`as_ref`]: #method.as_ref
+    /// [`as_uninit_slice_mut`]: #method.as_uninit_slice_mut
+    ///
+    /// # Safety
+    ///
+    /// When calling this method, you have to ensure that all of the following is true:
+    ///
+    /// * The pointer must be [valid] for reads for `ptr.len() * mem::size_of::<T>()` many bytes,
+    ///   and it must be properly aligned. This means in particular:
+    ///
+    ///     * The entire memory range of this slice must be contained within a single allocated object!
+    ///       Slices can never span across multiple allocated objects.
+    ///
+    ///     * The pointer must be aligned even for zero-length slices. One
+    ///       reason for this is that enum layout optimizations may rely on references
+    ///       (including slices of any length) being aligned and non-null to distinguish
+    ///       them from other data. You can obtain a pointer that is usable as `data`
+    ///       for zero-length slices using [`NonNull::dangling()`].
+    ///
+    /// * The total size `ptr.len() * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`.
+    ///   See the safety documentation of [`pointer::offset`].
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get mutated (except inside `UnsafeCell`).
+    ///
+    /// This applies even if the result of this method is unused!
+    ///
+    /// See also [`slice::from_raw_parts`][].
+    ///
+    /// [valid]: crate::ptr#safety
+    /// [`NonNull::dangling()`]: NonNull::dangling
+    /// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset
+    #[inline]
+    #[unstable(feature = "ptr_as_uninit", issue = "75402")]
+    pub unsafe fn as_uninit_slice(&self) -> &[MaybeUninit<T>] {
+        // SAFETY: the caller must uphold the safety contract for `as_uninit_slice`.
+        unsafe { slice::from_raw_parts(self.cast().as_ptr(), self.len()) }
+    }
+
+    /// Returns a unique reference to a slice of possibly uninitialized values. In contrast to
+    /// [`as_mut`], this does not require that the value has to be initialized.
+    ///
+    /// For the shared counterpart see [`as_uninit_slice`].
+    ///
+    /// [`as_mut`]: #method.as_mut
+    /// [`as_uninit_slice`]: #method.as_uninit_slice
+    ///
+    /// # Safety
+    ///
+    /// When calling this method, you have to ensure that all of the following is true:
+    ///
+    /// * The pointer must be [valid] for reads and writes for `ptr.len() * mem::size_of::<T>()`
+    ///   many bytes, and it must be properly aligned. This means in particular:
+    ///
+    ///     * The entire memory range of this slice must be contained within a single allocated object!
+    ///       Slices can never span across multiple allocated objects.
+    ///
+    ///     * The pointer must be aligned even for zero-length slices. One
+    ///       reason for this is that enum layout optimizations may rely on references
+    ///       (including slices of any length) being aligned and non-null to distinguish
+    ///       them from other data. You can obtain a pointer that is usable as `data`
+    ///       for zero-length slices using [`NonNull::dangling()`].
+    ///
+    /// * The total size `ptr.len() * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`.
+    ///   See the safety documentation of [`pointer::offset`].
+    ///
+    /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
+    ///   arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+    ///   In particular, for the duration of this lifetime, the memory the pointer points to must
+    ///   not get accessed (read or written) through any other pointer.
+    ///
+    /// This applies even if the result of this method is unused!
+    ///
+    /// See also [`slice::from_raw_parts_mut`][].
+    ///
+    /// [valid]: crate::ptr#safety
+    /// [`NonNull::dangling()`]: NonNull::dangling
+    /// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// #![feature(allocator_api, ptr_as_uninit)]
+    ///
+    /// use std::alloc::{AllocRef, Layout, Global};
+    /// use std::mem::MaybeUninit;
+    /// use std::ptr::NonNull;
+    ///
+    /// let memory: NonNull<[u8]> = Global.alloc(Layout::new::<[u8; 32]>())?;
+    /// // This is safe as `memory` is valid for reads and writes for `memory.len()` many bytes.
+    /// // Note that calling `memory.as_mut()` is not allowed here as the content may be uninitialized.
+    /// # #[allow(unused_variables)]
+    /// let slice: &mut [MaybeUninit<u8>] = unsafe { memory.as_uninit_slice_mut() };
+    /// # Ok::<_, std::alloc::AllocErr>(())
+    /// ```
+    #[inline]
+    #[unstable(feature = "ptr_as_uninit", issue = "75402")]
+    pub unsafe fn as_uninit_slice_mut(&self) -> &mut [MaybeUninit<T>] {
+        // SAFETY: the caller must uphold the safety contract for `as_uninit_slice_mut`.
+        unsafe { slice::from_raw_parts_mut(self.cast().as_ptr(), self.len()) }
+    }
+
     /// Returns a raw pointer to an element or subslice, without doing bounds
     /// checking.
     ///