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 {
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
///
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
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
///
/// 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]".
/// ```
///
/// 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")]
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`.
/// byte past the end of the same allocated object. Note that in Rust,
/// every (stack-allocated) variable is considered a separate allocated object.
///
+ /// * Both pointers must be *derived from* a pointer to the same object.
+ /// (See below for an example.)
+ ///
/// * The distance between the pointers, **in bytes**, cannot overflow an `isize`.
///
/// * The distance between the pointers, in bytes, must be an exact multiple
/// assert_eq!(ptr2.offset(-2), ptr1);
/// }
/// ```
- #[unstable(feature = "ptr_offset_from", issue = "41079")]
- #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079")]
- #[inline]
- pub const unsafe fn offset_from(self, origin: *const T) -> isize
- where
- T: Sized,
- {
- // SAFETY: the caller must uphold the safety contract for `offset_from`.
- unsafe { (self as *const T).offset_from(origin) }
- }
-
- /// Calculates the distance between two pointers. The returned value is in
- /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
- ///
- /// If the address different between the two pointers is not a multiple of
- /// `mem::size_of::<T>()` then the result of the division is rounded towards
- /// zero.
- ///
- /// Though this method is safe for any two pointers, note that its result
- /// will be mostly useless if the two pointers aren't into the same allocated
- /// object, for example if they point to two different local variables.
- ///
- /// # Panics
///
- /// This function panics if `T` is a zero-sized type.
- ///
- /// # Examples
- ///
- /// Basic usage:
+ /// *Incorrect* usage:
///
- /// ```
- /// #![feature(ptr_wrapping_offset_from)]
+ /// ```rust,no_run
+ /// #![feature(ptr_offset_from)]
///
- /// let mut a = [0; 5];
- /// let ptr1: *mut i32 = &mut a[1];
- /// let ptr2: *mut i32 = &mut a[3];
- /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
- /// assert_eq!(ptr1.wrapping_offset_from(ptr2), -2);
- /// assert_eq!(ptr1.wrapping_offset(2), ptr2);
- /// assert_eq!(ptr2.wrapping_offset(-2), ptr1);
- ///
- /// let ptr1: *mut i32 = 3 as _;
- /// let ptr2: *mut i32 = 13 as _;
- /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
+ /// let ptr1 = Box::into_raw(Box::new(0u8));
+ /// let ptr2 = Box::into_raw(Box::new(1u8));
+ /// let diff = (ptr2 as isize).wrapping_sub(ptr1 as isize);
+ /// // Make ptr2_other an "alias" of ptr2, but derived from ptr1.
+ /// let ptr2_other = (ptr1 as *mut u8).wrapping_offset(diff);
+ /// assert_eq!(ptr2 as usize, ptr2_other as usize);
+ /// // Since ptr2_other and ptr2 are derived from pointers to different objects,
+ /// // computing their offset is undefined behavior, even though
+ /// // they point to the same address!
+ /// unsafe {
+ /// let zero = ptr2_other.offset_from(ptr2); // Undefined Behavior
+ /// }
/// ```
- #[unstable(feature = "ptr_wrapping_offset_from", issue = "41079")]
- #[rustc_deprecated(
- since = "1.46.0",
- reason = "Pointer distances across allocation \
- boundaries are not typically meaningful. \
- Use integer subtraction if you really need this."
- )]
+ #[stable(feature = "ptr_offset_from", since = "1.46.0")]
+ #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079")]
#[inline]
- pub fn wrapping_offset_from(self, origin: *const T) -> isize
+ pub const unsafe fn offset_from(self, origin: *const T) -> isize
where
T: Sized,
{
- #[allow(deprecated_in_future, deprecated)]
- (self as *const T).wrapping_offset_from(origin)
+ // SAFETY: the caller must uphold the safety contract for `offset_from`.
+ unsafe { (self as *const T).offset_from(origin) }
}
/// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
// 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