Skip to content

Commit 93e074b

Browse files
committed
Add as_uninit-like methods to pointer types and unify documentation of as_ref methods
Fix example in `NonNull::as_uninit_slice` Rename feature gate to "ptr_as_uninit" Make methods more consistent with already stable methods Make `pointer::as_uninit_slice` return an `Option` Fix placement for `// SAFETY` section Add `as_uninit_ref` and `as_uninit_mut` to pointers Fix doctest Update tracking issue Fix doc links Apply suggestions from review Make wording about counterparts consistent Fix doc links Improve documentation Fix doc-tests Fix doc links ... again Apply suggestions from review Apply suggestions from Review Apply suggestion from review to all affected files Add missing words in safety sections in `as_uninit_slice_mut` Fix safety-comment in `NonNull::as_uninit_slice_mut`
1 parent 441fd22 commit 93e074b

File tree

4 files changed

+568
-81
lines changed

4 files changed

+568
-81
lines changed

library/core/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@
114114
#![feature(optin_builtin_traits)]
115115
#![feature(or_patterns)]
116116
#![feature(prelude_import)]
117+
#![feature(ptr_as_uninit)]
117118
#![feature(repr_simd, platform_intrinsics)]
118119
#![feature(rustc_attrs)]
119120
#![feature(simd_ffi)]

library/core/src/ptr/const_ptr.rs

+117-17
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::*;
22
use crate::cmp::Ordering::{self, Equal, Greater, Less};
33
use crate::intrinsics;
44
use crate::mem;
5-
use crate::slice::SliceIndex;
5+
use crate::slice::{self, SliceIndex};
66

77
#[lang = "const_ptr"]
88
impl<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

Comments
 (0)