Skip to content

Commit d6a1b36

Browse files
committed
Implement ptr_as_ref_unchecked (rust-lang#122034)
1 parent e69f14b commit d6a1b36

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
@@ -362,6 +362,54 @@ impl<T: ?Sized> *const T {
362362
if self.is_null() { None } else { unsafe { Some(&*self) } }
363363
}
364364

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

library/core/src/ptr/mut_ptr.rs

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

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

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

0 commit comments

Comments
 (0)