@@ -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 {
@@ -38,32 +38,33 @@ impl<T: ?Sized> *const T {
38
38
self as _
39
39
}
40
40
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.
43
44
///
44
- /// # Safety
45
+ /// [`as_uninit_ref`]: #method.as_uninit_ref
45
46
///
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
50
48
///
51
49
/// When calling this method, you have to ensure that *either* the pointer is NULL *or*
52
50
/// 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`).
56
62
///
57
63
/// This applies even if the result of this method is unused!
58
64
/// (The part about being initialized is not yet fully decided, but until
59
65
/// it is, the only safe approach is to ensure that they are indeed initialized.)
60
66
///
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
67
68
///
68
69
/// # Examples
69
70
///
@@ -101,6 +102,56 @@ impl<T: ?Sized> *const T {
101
102
if self . is_null ( ) { None } else { unsafe { Some ( & * self ) } }
102
103
}
103
104
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
+
104
155
/// Calculates the offset from a pointer.
105
156
///
106
157
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer
@@ -906,6 +957,55 @@ impl<T> *const [T] {
906
957
// SAFETY: the caller ensures that `self` is dereferencable and `index` in-bounds.
907
958
unsafe { index. get_unchecked ( self ) }
908
959
}
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
+ }
909
1009
}
910
1010
911
1011
// Equality for pointers
0 commit comments