Skip to content

Commit

Permalink
Rollup merge of #122492 - GrigorenkoPV:ptr_as_ref_unchecked, r=workin…
Browse files Browse the repository at this point in the history
…gjubilee

Implement ptr_as_ref_unchecked

Implementation of #122034.

Prefixed the feature name with `ptr_` for clarity.

Linked const-unstability to #91822, so the post there should probably be updated to mentions the 3 new methods when/if this PR is merged.
  • Loading branch information
matthiaskrgr authored May 3, 2024
2 parents d6d3b34 + d6a1b36 commit a296693
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 0 deletions.
48 changes: 48 additions & 0 deletions library/core/src/ptr/const_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,54 @@ impl<T: ?Sized> *const T {
if self.is_null() { None } else { unsafe { Some(&*self) } }
}

/// Returns a shared reference to the value behind the pointer.
/// If the pointer may be null or the value may be uninitialized, [`as_uninit_ref`] must be used instead.
/// If the pointer may be null, but the value is known to have been initialized, [`as_ref`] must be used instead.
///
/// [`as_ref`]: #method.as_ref
/// [`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 "dereferenceable" 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, while this reference exists, 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.)
///
/// [the module documentation]: crate::ptr#safety
///
/// # Examples
///
/// ```
/// #![feature(ptr_as_ref_unchecked)]
/// let ptr: *const u8 = &10u8 as *const u8;
///
/// unsafe {
/// println!("We got back the value: {}!", ptr.as_ref_unchecked());
/// }
/// ```
// FIXME: mention it in the docs for `as_ref` and `as_uninit_ref` once stabilized.
#[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")]
#[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
#[inline]
#[must_use]
pub const unsafe fn as_ref_unchecked<'a>(self) -> &'a T {
// SAFETY: the caller must guarantee that `self` is valid for a reference
unsafe { &*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.
Expand Down
103 changes: 103 additions & 0 deletions library/core/src/ptr/mut_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,57 @@ impl<T: ?Sized> *mut T {
if self.is_null() { None } else { unsafe { Some(&*self) } }
}

/// Returns a shared reference to the value behind the pointer.
/// If the pointer may be null or the value may be uninitialized, [`as_uninit_ref`] must be used instead.
/// If the pointer may be null, but the value is known to have been initialized, [`as_ref`] must be used instead.
///
/// For the mutable counterpart see [`as_mut_unchecked`].
///
/// [`as_ref`]: #method.as_ref
/// [`as_uninit_ref`]: #method.as_uninit_ref
/// [`as_mut_unchecked`]: #method.as_mut_unchecked
///
/// # 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 "dereferenceable" 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, while this reference exists, 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.)
///
/// [the module documentation]: crate::ptr#safety
///
/// # Examples
///
/// ```
/// #![feature(ptr_as_ref_unchecked)]
/// let ptr: *mut u8 = &mut 10u8 as *mut u8;
///
/// unsafe {
/// println!("We got back the value: {}!", ptr.as_ref_unchecked());
/// }
/// ```
// FIXME: mention it in the docs for `as_ref` and `as_uninit_ref` once stabilized.
#[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")]
#[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
#[inline]
#[must_use]
pub const unsafe fn as_ref_unchecked<'a>(self) -> &'a T {
// SAFETY: the caller must guarantee that `self` is valid for a reference
unsafe { &*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.
Expand Down Expand Up @@ -688,6 +739,58 @@ impl<T: ?Sized> *mut T {
if self.is_null() { None } else { unsafe { Some(&mut *self) } }
}

/// Returns a unique reference to the value behind the pointer.
/// If the pointer may be null or the value may be uninitialized, [`as_uninit_mut`] must be used instead.
/// If the pointer may be null, but the value is known to have been initialized, [`as_mut`] must be used instead.
///
/// For the shared counterpart see [`as_ref_unchecked`].
///
/// [`as_mut`]: #method.as_mut
/// [`as_uninit_mut`]: #method.as_uninit_mut
/// [`as_ref_unchecked`]: #method.as_mut_unchecked
///
/// # 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 "dereferenceable" 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, while this reference exists, 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.)
///
/// [the module documentation]: crate::ptr#safety
///
/// # Examples
///
/// ```
/// #![feature(ptr_as_ref_unchecked)]
/// let mut s = [1, 2, 3];
/// let ptr: *mut u32 = s.as_mut_ptr();
/// let first_value = unsafe { ptr.as_mut_unchecked() };
/// *first_value = 4;
/// # assert_eq!(s, [4, 2, 3]);
/// println!("{s:?}"); // It'll print: "[4, 2, 3]".
/// ```
// FIXME: mention it in the docs for `as_mut` and `as_uninit_mut` once stabilized.
#[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")]
#[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
#[inline]
#[must_use]
pub const unsafe fn as_mut_unchecked<'a>(self) -> &'a mut T {
// SAFETY: the caller must guarantee that `self` is valid for a reference
unsafe { &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.
Expand Down

0 comments on commit a296693

Please sign in to comment.