@@ -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 {
@@ -38,32 +38,33 @@ impl<T: ?Sized> *const T {
3838 self as _
3939 }
4040
41- /// Returns `None` if the pointer is null, or else returns a reference to
42- /// the value wrapped in `Some`.
41+ /// Returns `None` if the pointer is null, or else returns a shared reference to
42+ /// the value wrapped in `Some`. If the value may be uninitialized, [`as_uninit_ref`]
43+ /// must be used instead.
4344 ///
44- /// # Safety
45+ /// [`as_uninit_ref`]: #method.as_uninit_ref
4546 ///
46- /// While this method and its mutable counterpart are useful for
47- /// null-safety, it is important to note that this is still an unsafe
48- /// operation because the returned value could be pointing to invalid
49- /// memory.
47+ /// # Safety
5048 ///
5149 /// When calling this method, you have to ensure that *either* the pointer is NULL *or*
5250 /// all of the following is true:
53- /// - it is properly aligned
54- /// - it must point to an initialized instance of T; in particular, the pointer must be
55- /// "dereferenceable" in the sense defined [here].
51+ ///
52+ /// * The pointer must be properly aligned.
53+ ///
54+ /// * It must be "dereferencable" in the sense defined in [the module documentation].
55+ ///
56+ /// * The pointer must point to an initialized instance of `T`.
57+ ///
58+ /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
59+ /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
60+ /// In particular, for the duration of this lifetime, the memory the pointer points to must
61+ /// not get mutated (except inside `UnsafeCell`).
5662 ///
5763 /// This applies even if the result of this method is unused!
5864 /// (The part about being initialized is not yet fully decided, but until
5965 /// it is, the only safe approach is to ensure that they are indeed initialized.)
6066 ///
61- /// Additionally, the lifetime `'a` returned is arbitrarily chosen and does
62- /// not necessarily reflect the actual lifetime of the data. *You* must enforce
63- /// Rust's aliasing rules. In particular, for the duration of this lifetime,
64- /// the memory the pointer points to must not get mutated (except inside `UnsafeCell`).
65- ///
66- /// [here]: crate::ptr#safety
67+ /// [the module documentation]: crate::ptr#safety
6768 ///
6869 /// # Examples
6970 ///
@@ -101,6 +102,56 @@ impl<T: ?Sized> *const T {
101102 if self . is_null ( ) { None } else { unsafe { Some ( & * self ) } }
102103 }
103104
105+ /// Returns `None` if the pointer is null, or else returns a shared reference to
106+ /// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require
107+ /// that the value has to be initialized.
108+ ///
109+ /// [`as_ref`]: #method.as_ref
110+ ///
111+ /// # Safety
112+ ///
113+ /// When calling this method, you have to ensure that *either* the pointer is NULL *or*
114+ /// all of the following is true:
115+ ///
116+ /// * The pointer must be properly aligned.
117+ ///
118+ /// * It must be "dereferencable" in the sense defined in [the module documentation].
119+ ///
120+ /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
121+ /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
122+ /// In particular, for the duration of this lifetime, the memory the pointer points to must
123+ /// not get mutated (except inside `UnsafeCell`).
124+ ///
125+ /// This applies even if the result of this method is unused!
126+ ///
127+ /// [the module documentation]: crate::ptr#safety
128+ ///
129+ /// # Examples
130+ ///
131+ /// Basic usage:
132+ ///
133+ /// ```
134+ /// #![feature(ptr_as_uninit)]
135+ ///
136+ /// let ptr: *const u8 = &10u8 as *const u8;
137+ ///
138+ /// unsafe {
139+ /// if let Some(val_back) = ptr.as_uninit_ref() {
140+ /// println!("We got back the value: {}!", val_back.assume_init());
141+ /// }
142+ /// }
143+ /// ```
144+ #[ inline]
145+ #[ unstable( feature = "ptr_as_uninit" , issue = "75402" ) ]
146+ pub unsafe fn as_uninit_ref < ' a > ( self ) -> Option < & ' a MaybeUninit < T > >
147+ where
148+ T : Sized ,
149+ {
150+ // SAFETY: the caller must guarantee that `self` meets all the
151+ // requirements for a reference.
152+ if self . is_null ( ) { None } else { Some ( unsafe { & * ( self as * const MaybeUninit < T > ) } ) }
153+ }
154+
104155 /// Calculates the offset from a pointer.
105156 ///
106157 /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
@@ -906,6 +957,55 @@ impl<T> *const [T] {
906957 // SAFETY: the caller ensures that `self` is dereferencable and `index` in-bounds.
907958 unsafe { index. get_unchecked ( self ) }
908959 }
960+
961+ /// Returns `None` if the pointer is null, or else returns a shared slice to
962+ /// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require
963+ /// that the value has to be initialized.
964+ ///
965+ /// [`as_ref`]: #method.as_ref
966+ ///
967+ /// # Safety
968+ ///
969+ /// When calling this method, you have to ensure that *either* the pointer is NULL *or*
970+ /// all of the following is true:
971+ ///
972+ /// * The pointer must be [valid] for reads for `ptr.len() * mem::size_of::<T>()` many bytes,
973+ /// and it must be properly aligned. This means in particular:
974+ ///
975+ /// * The entire memory range of this slice must be contained within a single allocated object!
976+ /// Slices can never span across multiple allocated objects.
977+ ///
978+ /// * The pointer must be aligned even for zero-length slices. One
979+ /// reason for this is that enum layout optimizations may rely on references
980+ /// (including slices of any length) being aligned and non-null to distinguish
981+ /// them from other data. You can obtain a pointer that is usable as `data`
982+ /// for zero-length slices using [`NonNull::dangling()`].
983+ ///
984+ /// * The total size `ptr.len() * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`.
985+ /// See the safety documentation of [`pointer::offset`].
986+ ///
987+ /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
988+ /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
989+ /// In particular, for the duration of this lifetime, the memory the pointer points to must
990+ /// not get mutated (except inside `UnsafeCell`).
991+ ///
992+ /// This applies even if the result of this method is unused!
993+ ///
994+ /// See also [`slice::from_raw_parts`][].
995+ ///
996+ /// [valid]: crate::ptr#safety
997+ /// [`NonNull::dangling()`]: NonNull::dangling
998+ /// [`pointer::offset`]: ../std/primitive.pointer.html#method.offset
999+ #[ inline]
1000+ #[ unstable( feature = "ptr_as_uninit" , issue = "75402" ) ]
1001+ pub unsafe fn as_uninit_slice < ' a > ( self ) -> Option < & ' a [ MaybeUninit < T > ] > {
1002+ if self . is_null ( ) {
1003+ None
1004+ } else {
1005+ // SAFETY: the caller must uphold the safety contract for `as_uninit_slice`.
1006+ Some ( unsafe { slice:: from_raw_parts ( self as * const MaybeUninit < T > , self . len ( ) ) } )
1007+ }
1008+ }
9091009}
9101010
9111011// Equality for pointers
0 commit comments