@@ -2,7 +2,7 @@ use super::*;
2
2
use crate :: cmp:: Ordering :: { self , Equal , Greater , Less } ;
3
3
use crate :: intrinsics;
4
4
use crate :: mem;
5
- use crate :: slice:: SliceIndex ;
5
+ use crate :: slice:: { self , SliceIndex } ;
6
6
7
7
#[ lang = "const_ptr" ]
8
8
impl < T : ?Sized > * const T {
@@ -48,32 +48,33 @@ impl<T: ?Sized> *const T {
48
48
self as _
49
49
}
50
50
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.
53
54
///
54
- /// # Safety
55
+ /// [`as_uninit_ref`]: #method.as_uninit_ref
55
56
///
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
60
58
///
61
59
/// When calling this method, you have to ensure that *either* the pointer is NULL *or*
62
60
/// 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`).
66
72
///
67
73
/// This applies even if the result of this method is unused!
68
74
/// (The part about being initialized is not yet fully decided, but until
69
75
/// it is, the only safe approach is to ensure that they are indeed initialized.)
70
76
///
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
77
78
///
78
79
/// # Examples
79
80
///
@@ -111,6 +112,56 @@ impl<T: ?Sized> *const T {
111
112
if self . is_null ( ) { None } else { unsafe { Some ( & * self ) } }
112
113
}
113
114
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
+
114
165
/// Calculates the offset from a pointer.
115
166
///
116
167
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer
@@ -925,6 +976,55 @@ impl<T> *const [T] {
925
976
// SAFETY: the caller ensures that `self` is dereferencable and `index` in-bounds.
926
977
unsafe { index. get_unchecked ( self ) }
927
978
}
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
+ }
928
1028
}
929
1029
930
1030
// Equality for pointers
0 commit comments