Skip to content

Commit a296693

Browse files
authored
Rollup merge of #122492 - GrigorenkoPV:ptr_as_ref_unchecked, r=workingjubilee
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.
2 parents d6d3b34 + d6a1b36 commit a296693

File tree

2 files changed

+151
-0
lines changed

2 files changed

+151
-0
lines changed

library/core/src/ptr/const_ptr.rs

+48
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,54 @@ impl<T: ?Sized> *const T {
358358
if self.is_null() { None } else { unsafe { Some(&*self) } }
359359
}
360360

361+
/// Returns a shared reference to the value behind the pointer.
362+
/// If the pointer may be null or the value may be uninitialized, [`as_uninit_ref`] must be used instead.
363+
/// If the pointer may be null, but the value is known to have been initialized, [`as_ref`] must be used instead.
364+
///
365+
/// [`as_ref`]: #method.as_ref
366+
/// [`as_uninit_ref`]: #method.as_uninit_ref
367+
///
368+
/// # Safety
369+
///
370+
/// When calling this method, you have to ensure that all of the following is true:
371+
///
372+
/// * The pointer must be properly aligned.
373+
///
374+
/// * It must be "dereferenceable" in the sense defined in [the module documentation].
375+
///
376+
/// * The pointer must point to an initialized instance of `T`.
377+
///
378+
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
379+
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
380+
/// In particular, while this reference exists, the memory the pointer points to must
381+
/// not get mutated (except inside `UnsafeCell`).
382+
///
383+
/// This applies even if the result of this method is unused!
384+
/// (The part about being initialized is not yet fully decided, but until
385+
/// it is, the only safe approach is to ensure that they are indeed initialized.)
386+
///
387+
/// [the module documentation]: crate::ptr#safety
388+
///
389+
/// # Examples
390+
///
391+
/// ```
392+
/// #![feature(ptr_as_ref_unchecked)]
393+
/// let ptr: *const u8 = &10u8 as *const u8;
394+
///
395+
/// unsafe {
396+
/// println!("We got back the value: {}!", ptr.as_ref_unchecked());
397+
/// }
398+
/// ```
399+
// FIXME: mention it in the docs for `as_ref` and `as_uninit_ref` once stabilized.
400+
#[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")]
401+
#[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
402+
#[inline]
403+
#[must_use]
404+
pub const unsafe fn as_ref_unchecked<'a>(self) -> &'a T {
405+
// SAFETY: the caller must guarantee that `self` is valid for a reference
406+
unsafe { &*self }
407+
}
408+
361409
/// Returns `None` if the pointer is null, or else returns a shared reference to
362410
/// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require
363411
/// that the value has to be initialized.

library/core/src/ptr/mut_ptr.rs

+103
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,57 @@ impl<T: ?Sized> *mut T {
367367
if self.is_null() { None } else { unsafe { Some(&*self) } }
368368
}
369369

370+
/// Returns a shared reference to the value behind the pointer.
371+
/// If the pointer may be null or the value may be uninitialized, [`as_uninit_ref`] must be used instead.
372+
/// If the pointer may be null, but the value is known to have been initialized, [`as_ref`] must be used instead.
373+
///
374+
/// For the mutable counterpart see [`as_mut_unchecked`].
375+
///
376+
/// [`as_ref`]: #method.as_ref
377+
/// [`as_uninit_ref`]: #method.as_uninit_ref
378+
/// [`as_mut_unchecked`]: #method.as_mut_unchecked
379+
///
380+
/// # Safety
381+
///
382+
/// When calling this method, you have to ensure that all of the following is true:
383+
///
384+
/// * The pointer must be properly aligned.
385+
///
386+
/// * It must be "dereferenceable" in the sense defined in [the module documentation].
387+
///
388+
/// * The pointer must point to an initialized instance of `T`.
389+
///
390+
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
391+
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
392+
/// In particular, while this reference exists, the memory the pointer points to must
393+
/// not get mutated (except inside `UnsafeCell`).
394+
///
395+
/// This applies even if the result of this method is unused!
396+
/// (The part about being initialized is not yet fully decided, but until
397+
/// it is, the only safe approach is to ensure that they are indeed initialized.)
398+
///
399+
/// [the module documentation]: crate::ptr#safety
400+
///
401+
/// # Examples
402+
///
403+
/// ```
404+
/// #![feature(ptr_as_ref_unchecked)]
405+
/// let ptr: *mut u8 = &mut 10u8 as *mut u8;
406+
///
407+
/// unsafe {
408+
/// println!("We got back the value: {}!", ptr.as_ref_unchecked());
409+
/// }
410+
/// ```
411+
// FIXME: mention it in the docs for `as_ref` and `as_uninit_ref` once stabilized.
412+
#[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")]
413+
#[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
414+
#[inline]
415+
#[must_use]
416+
pub const unsafe fn as_ref_unchecked<'a>(self) -> &'a T {
417+
// SAFETY: the caller must guarantee that `self` is valid for a reference
418+
unsafe { &*self }
419+
}
420+
370421
/// Returns `None` if the pointer is null, or else returns a shared reference to
371422
/// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require
372423
/// that the value has to be initialized.
@@ -688,6 +739,58 @@ impl<T: ?Sized> *mut T {
688739
if self.is_null() { None } else { unsafe { Some(&mut *self) } }
689740
}
690741

742+
/// Returns a unique reference to the value behind the pointer.
743+
/// If the pointer may be null or the value may be uninitialized, [`as_uninit_mut`] must be used instead.
744+
/// If the pointer may be null, but the value is known to have been initialized, [`as_mut`] must be used instead.
745+
///
746+
/// For the shared counterpart see [`as_ref_unchecked`].
747+
///
748+
/// [`as_mut`]: #method.as_mut
749+
/// [`as_uninit_mut`]: #method.as_uninit_mut
750+
/// [`as_ref_unchecked`]: #method.as_mut_unchecked
751+
///
752+
/// # Safety
753+
///
754+
/// When calling this method, you have to ensure that all of the following is true:
755+
///
756+
/// * The pointer must be properly aligned.
757+
///
758+
/// * It must be "dereferenceable" in the sense defined in [the module documentation].
759+
///
760+
/// * The pointer must point to an initialized instance of `T`.
761+
///
762+
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
763+
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
764+
/// In particular, while this reference exists, the memory the pointer points to must
765+
/// not get mutated (except inside `UnsafeCell`).
766+
///
767+
/// This applies even if the result of this method is unused!
768+
/// (The part about being initialized is not yet fully decided, but until
769+
/// it is, the only safe approach is to ensure that they are indeed initialized.)
770+
///
771+
/// [the module documentation]: crate::ptr#safety
772+
///
773+
/// # Examples
774+
///
775+
/// ```
776+
/// #![feature(ptr_as_ref_unchecked)]
777+
/// let mut s = [1, 2, 3];
778+
/// let ptr: *mut u32 = s.as_mut_ptr();
779+
/// let first_value = unsafe { ptr.as_mut_unchecked() };
780+
/// *first_value = 4;
781+
/// # assert_eq!(s, [4, 2, 3]);
782+
/// println!("{s:?}"); // It'll print: "[4, 2, 3]".
783+
/// ```
784+
// FIXME: mention it in the docs for `as_mut` and `as_uninit_mut` once stabilized.
785+
#[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")]
786+
#[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
787+
#[inline]
788+
#[must_use]
789+
pub const unsafe fn as_mut_unchecked<'a>(self) -> &'a mut T {
790+
// SAFETY: the caller must guarantee that `self` is valid for a reference
791+
unsafe { &mut *self }
792+
}
793+
691794
/// Returns `None` if the pointer is null, or else returns a unique reference to
692795
/// the value wrapped in `Some`. In contrast to [`as_mut`], this does not require
693796
/// that the value has to be initialized.

0 commit comments

Comments
 (0)