Add as_uninit
-like methods to pointer types and unify documentation of as_ref
methods
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`
This commit is contained in:
parent
441fd22557
commit
93e074bc8a
@ -114,6 +114,7 @@
|
||||
#![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)]
|
||||
|
@ -2,7 +2,7 @@ use super::*;
|
||||
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 @@ impl<T: ?Sized> *const T {
|
||||
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.
|
||||
///
|
||||
/// [`as_uninit_ref`]: #method.as_uninit_ref
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// 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 @@ impl<T: ?Sized> *const 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 @@ impl<T> *const [T] {
|
||||
// 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
|
||||
|
@ -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 @@ impl<T: ?Sized> *mut T {
|
||||
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.
|
||||
///
|
||||
/// For the mutable counterpart see [`as_mut`].
|
||||
///
|
||||
/// [`as_uninit_ref`]: #method.as_uninit_ref-1
|
||||
/// [`as_mut`]: #method.as_mut
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// 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 @@ impl<T: ?Sized> *mut 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 @@ impl<T: ?Sized> *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.
|
||||
///
|
||||
/// For the shared counterpart see [`as_ref`].
|
||||
///
|
||||
/// [`as_uninit_mut`]: #method.as_uninit_mut
|
||||
/// [`as_ref`]: #method.as_ref-1
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// 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.)
|
||||
/// 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.
|
||||
///
|
||||
/// [here]: crate::ptr#safety
|
||||
/// [`as_ref`]: #method.as_ref
|
||||
/// [the module documentation]: crate::ptr#safety
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -262,6 +322,7 @@ impl<T: ?Sized> *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 @@ impl<T: ?Sized> *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 @@ impl<T: ?Sized> *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 @@ impl<T> *mut [T] {
|
||||
// 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
|
||||
|
@ -3,10 +3,10 @@ use crate::convert::From;
|
||||
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 @@ impl<T: Sized> NonNull<T> {
|
||||
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 @@ impl<T: ?Sized> NonNull<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.
|
||||
///
|
||||
/// 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()`.
|
||||
/// For the mutable counterpart see [`as_mut`].
|
||||
///
|
||||
/// [`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 @@ impl<T: ?Sized> NonNull<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.
|
||||
///
|
||||
/// 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()`.
|
||||
/// For the shared counterpart see [`as_ref`].
|
||||
///
|
||||
/// [`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.)
|
||||
/// 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.
|
||||
///
|
||||
/// [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 @@ impl<T> NonNull<[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.
|
||||
///
|
||||
|
Loading…
x
Reference in New Issue
Block a user