@@ -2,7 +2,7 @@ use super::*;
22use crate :: cmp:: Ordering :: { self , Equal , Greater , Less } ;
33use crate :: intrinsics;
44use crate :: mem;
5- use crate :: slice:: SliceIndex ;
5+ use crate :: slice:: { self , SliceIndex } ;
66
77#[ lang = "const_ptr" ]
88impl < T : ?Sized > * const T {
@@ -48,32 +48,33 @@ impl<T: ?Sized> *const T {
4848 self as _
4949 }
5050
51- /// Returns `None` if the pointer is null, or else returns a reference to
52- /// the value wrapped in `Some`.
51+ /// Returns `None` if the pointer is null, or else returns a shared reference to
52+ /// the value wrapped in `Some`. If the value may be uninitialized, [`as_uninit_ref`]
53+ /// must be used instead.
5354 ///
54- /// # Safety
55+ /// [`as_uninit_ref`]: #method.as_uninit_ref
5556 ///
56- /// While this method and its mutable counterpart are useful for
57- /// null-safety, it is important to note that this is still an unsafe
58- /// operation because the returned value could be pointing to invalid
59- /// memory.
57+ /// # Safety
6058 ///
6159 /// When calling this method, you have to ensure that *either* the pointer is NULL *or*
6260 /// all of the following is true:
63- /// - it is properly aligned
64- /// - it must point to an initialized instance of T; in particular, the pointer must be
65- /// "dereferenceable" in the sense defined [here].
61+ ///
62+ /// * The pointer must be properly aligned.
63+ ///
64+ /// * It must be "dereferencable" in the sense defined in [the module documentation].
65+ ///
66+ /// * The pointer must point to an initialized instance of `T`.
67+ ///
68+ /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
69+ /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
70+ /// In particular, for the duration of this lifetime, the memory the pointer points to must
71+ /// not get mutated (except inside `UnsafeCell`).
6672 ///
6773 /// This applies even if the result of this method is unused!
6874 /// (The part about being initialized is not yet fully decided, but until
6975 /// it is, the only safe approach is to ensure that they are indeed initialized.)
7076 ///
71- /// Additionally, the lifetime `'a` returned is arbitrarily chosen and does
72- /// not necessarily reflect the actual lifetime of the data. *You* must enforce
73- /// Rust's aliasing rules. In particular, for the duration of this lifetime,
74- /// the memory the pointer points to must not get mutated (except inside `UnsafeCell`).
75- ///
76- /// [here]: crate::ptr#safety
77+ /// [the module documentation]: crate::ptr#safety
7778 ///
7879 /// # Examples
7980 ///
@@ -111,6 +112,56 @@ impl<T: ?Sized> *const T {
111112 if self . is_null ( ) { None } else { unsafe { Some ( & * self ) } }
112113 }
113114
115+ /// Returns `None` if the pointer is null, or else returns a shared reference to
116+ /// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require
117+ /// that the value has to be initialized.
118+ ///
119+ /// [`as_ref`]: #method.as_ref
120+ ///
121+ /// # Safety
122+ ///
123+ /// When calling this method, you have to ensure that *either* the pointer is NULL *or*
124+ /// all of the following is true:
125+ ///
126+ /// * The pointer must be properly aligned.
127+ ///
128+ /// * It must be "dereferencable" in the sense defined in [the module documentation].
129+ ///
130+ /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
131+ /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
132+ /// In particular, for the duration of this lifetime, the memory the pointer points to must
133+ /// not get mutated (except inside `UnsafeCell`).
134+ ///
135+ /// This applies even if the result of this method is unused!
136+ ///
137+ /// [the module documentation]: crate::ptr#safety
138+ ///
139+ /// # Examples
140+ ///
141+ /// Basic usage:
142+ ///
143+ /// ```
144+ /// #![feature(ptr_as_uninit)]
145+ ///
146+ /// let ptr: *const u8 = &10u8 as *const u8;
147+ ///
148+ /// unsafe {
149+ /// if let Some(val_back) = ptr.as_uninit_ref() {
150+ /// println!("We got back the value: {}!", val_back.assume_init());
151+ /// }
152+ /// }
153+ /// ```
154+ #[ inline]
155+ #[ unstable( feature = "ptr_as_uninit" , issue = "75402" ) ]
156+ pub unsafe fn as_uninit_ref < ' a > ( self ) -> Option < & ' a MaybeUninit < T > >
157+ where
158+ T : Sized ,
159+ {
160+ // SAFETY: the caller must guarantee that `self` meets all the
161+ // requirements for a reference.
162+ if self . is_null ( ) { None } else { Some ( unsafe { & * ( self as * const MaybeUninit < T > ) } ) }
163+ }
164+
114165 /// Calculates the offset from a pointer.
115166 ///
116167 /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
@@ -925,6 +976,55 @@ impl<T> *const [T] {
925976 // SAFETY: the caller ensures that `self` is dereferencable and `index` in-bounds.
926977 unsafe { index. get_unchecked ( self ) }
927978 }
979+
980+ /// Returns `None` if the pointer is null, or else returns a shared slice to
981+ /// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require
982+ /// that the value has to be initialized.
983+ ///
984+ /// [`as_ref`]: #method.as_ref
985+ ///
986+ /// # Safety
987+ ///
988+ /// When calling this method, you have to ensure that *either* the pointer is NULL *or*
989+ /// all of the following is true:
990+ ///
991+ /// * The pointer must be [valid] for reads for `ptr.len() * mem::size_of::<T>()` many bytes,
992+ /// and it must be properly aligned. This means in particular:
993+ ///
994+ /// * The entire memory range of this slice must be contained within a single allocated object!
995+ /// Slices can never span across multiple allocated objects.
996+ ///
997+ /// * The pointer must be aligned even for zero-length slices. One
998+ /// reason for this is that enum layout optimizations may rely on references
999+ /// (including slices of any length) being aligned and non-null to distinguish
1000+ /// them from other data. You can obtain a pointer that is usable as `data`
1001+ /// for zero-length slices using [`NonNull::dangling()`].
1002+ ///
1003+ /// * The total size `ptr.len() * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`.
1004+ /// See the safety documentation of [`pointer::offset`].
1005+ ///
1006+ /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
1007+ /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
1008+ /// In particular, for the duration of this lifetime, the memory the pointer points to must
1009+ /// not get mutated (except inside `UnsafeCell`).
1010+ ///
1011+ /// This applies even if the result of this method is unused!
1012+ ///
1013+ /// See also [`slice::from_raw_parts`][].
1014+ ///
1015+ /// [valid]: crate::ptr#safety
1016+ /// [`NonNull::dangling()`]: NonNull::dangling
1017+ /// [`pointer::offset`]: ../std/primitive.pointer.html#method.offset
1018+ #[ inline]
1019+ #[ unstable( feature = "ptr_as_uninit" , issue = "75402" ) ]
1020+ pub unsafe fn as_uninit_slice < ' a > ( self ) -> Option < & ' a [ MaybeUninit < T > ] > {
1021+ if self . is_null ( ) {
1022+ None
1023+ } else {
1024+ // SAFETY: the caller must uphold the safety contract for `as_uninit_slice`.
1025+ Some ( unsafe { slice:: from_raw_parts ( self as * const MaybeUninit < T > , self . len ( ) ) } )
1026+ }
1027+ }
9281028}
9291029
9301030// Equality for pointers
0 commit comments