split MaybeUninit into several features, expand docs a bit

This commit is contained in:
Ralf Jung 2019-02-14 20:00:16 +01:00
parent e544947278
commit b5ab2c7f1c
5 changed files with 55 additions and 33 deletions

View File

@ -453,7 +453,7 @@ pub fn ascend(self) -> Result<
root: self.root,
_marker: PhantomData
},
idx: unsafe { usize::from(*self.as_header().parent_idx.get_ref()) },
idx: unsafe { usize::from(*self.as_header().parent_idx.as_ptr()) },
_marker: PhantomData
})
} else {
@ -1143,7 +1143,7 @@ pub fn descend(self) -> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
NodeRef {
height: self.node.height - 1,
node: unsafe {
self.node.as_internal().edges.get_unchecked(self.idx).get_ref().as_ptr()
(&*self.node.as_internal().edges.get_unchecked(self.idx).as_ptr()).as_ptr()
},
root: self.node.root,
_marker: PhantomData

View File

@ -112,7 +112,7 @@
#![feature(rustc_const_unstable)]
#![feature(const_vec_new)]
#![feature(slice_partition_dedup)]
#![feature(maybe_uninit)]
#![feature(maybe_uninit, maybe_uninit_slice)]
#![feature(alloc_layout_extra)]
#![feature(try_trait)]

View File

@ -122,7 +122,7 @@
#![feature(structural_match)]
#![feature(abi_unadjusted)]
#![feature(adx_target_feature)]
#![feature(maybe_uninit)]
#![feature(maybe_uninit, maybe_uninit_slice)]
#![feature(unrestricted_attribute_tokens)]
#[prelude_import]

View File

@ -563,11 +563,11 @@ macro_rules! unimplemented {
/// A macro to create an array of [`MaybeUninit`]
///
/// This macro constructs and uninitialized array of the type `[MaybeUninit<K>; N]`.
/// This macro constructs an uninitialized array of the type `[MaybeUninit<K>; N]`.
///
/// [`MaybeUninit`]: mem/union.MaybeUninit.html
#[macro_export]
#[unstable(feature = "maybe_uninit", issue = "53491")]
#[unstable(feature = "maybe_uninit_slice", issue = "53491")]
macro_rules! uninitialized_array {
// This `into_initialized` is safe because an array of `MaybeUninit` does not
// require initialization.

View File

@ -1045,17 +1045,34 @@ fn deref_mut(&mut self) -> &mut T {
/// ever gets used to access memory:
///
/// ```rust,no_run
/// use std::mem;
/// #![feature(maybe_uninit)]
/// use std::mem::{self, MaybeUninit};
///
/// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior!
/// // equivalent code with `MaybeUninit`
/// let x: &i32 = unsafe { MaybeUninit::zeroed().into_initialized() }; // undefined behavior!
/// ```
///
/// This is exploited by the compiler for various optimizations, such as eliding
/// run-time checks and optimizing `enum` layout.
///
/// Not initializing memory at all (instead of zero--initializing it) causes the same
/// Not initializing memory at all (instead of zero-initializing it) causes the same
/// issue: after all, the initial value of the variable might just happen to be
/// one that violates the invariant.
/// one that violates the invariant. Moreover, uninitialized memory is special
/// in that the compiler knows that it does not have a fixed value. This makes
/// it undefined behavior to have uninitialized data in a variable even if that
/// variable has otherwise no restrictions about which values are valid:
///
/// ```rust,no_run
/// #![feature(maybe_uninit)]
/// use std::mem::{self, MaybeUninit};
///
/// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior!
/// // equivalent code with `MaybeUninit`
/// let x: i32 = unsafe { MaybeUninit::uninitialized().into_initialized() }; // undefined behavior!
/// ```
/// (Notice that the rules around uninitialized integers are not finalized yet, but
/// until they are, it is advisable to avoid them.)
///
/// `MaybeUninit` serves to enable unsafe code to deal with uninitialized data:
/// it is a signal to the compiler indicating that the data here might *not*
@ -1065,7 +1082,8 @@ fn deref_mut(&mut self) -> &mut T {
/// #![feature(maybe_uninit)]
/// use std::mem::MaybeUninit;
///
/// // Create an explicitly uninitialized reference.
/// // Create an explicitly uninitialized reference. The compiler knows that data inside
/// // a `MaybeUninit` may be invalid, and hence this is not UB:
/// let mut x = MaybeUninit::<&i32>::uninitialized();
/// // Set it to a valid value.
/// x.set(&0);
@ -1075,6 +1093,7 @@ fn deref_mut(&mut self) -> &mut T {
/// ```
///
/// The compiler then knows to not optimize this code.
// FIXME before stabilizing, explain how to initialize a struct field-by-field.
#[allow(missing_debug_implementations)]
#[unstable(feature = "maybe_uninit", issue = "53491")]
// NOTE after stabilizing `MaybeUninit` proceed to deprecate `mem::{uninitialized,zeroed}`
@ -1134,6 +1153,22 @@ pub fn set(&mut self, val: T) -> &mut T {
}
}
/// Gets a pointer to the contained value. Reading from this pointer or turning it
/// into a reference will be undefined behavior unless the `MaybeUninit` is initialized.
#[unstable(feature = "maybe_uninit", issue = "53491")]
#[inline(always)]
pub fn as_ptr(&self) -> *const T {
unsafe { &*self.value as *const T }
}
/// Gets a mutable pointer to the contained value. Reading from this pointer or turning it
/// into a reference will be undefined behavior unless the `MaybeUninit` is initialized.
#[unstable(feature = "maybe_uninit", issue = "53491")]
#[inline(always)]
pub fn as_mut_ptr(&mut self) -> *mut T {
unsafe { &mut *self.value as *mut T }
}
/// Extracts the value from the `MaybeUninit` container. This is a great way
/// to ensure that the data will get dropped, because the resulting `T` is
/// subject to the usual drop handling.
@ -1141,7 +1176,8 @@ pub fn set(&mut self, val: T) -> &mut T {
/// # Unsafety
///
/// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized
/// state, otherwise this will immediately cause undefined behavior.
/// state. Calling this when the content is not yet fully initialized causes undefined
/// behavior.
#[unstable(feature = "maybe_uninit", issue = "53491")]
#[inline(always)]
pub unsafe fn into_initialized(self) -> T {
@ -1162,8 +1198,9 @@ pub(crate) unsafe fn into_inner(self) -> T {
/// # Unsafety
///
/// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized
/// state, otherwise this will immediately cause undefined behavior.
#[unstable(feature = "maybe_uninit", issue = "53491")]
/// state. Calling this when the content is not yet fully initialized causes undefined
/// behavior.
#[unstable(feature = "maybe_uninit_ref", issue = "53491")]
#[inline(always)]
pub unsafe fn get_ref(&self) -> &T {
&*self.value
@ -1174,41 +1211,26 @@ pub unsafe fn get_ref(&self) -> &T {
/// # Unsafety
///
/// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized
/// state, otherwise this will immediately cause undefined behavior.
/// state. Calling this when the content is not yet fully initialized causes undefined
/// behavior.
// FIXME(#53491): We currently rely on the above being incorrect, i.e., we have references
// to uninitialized data (e.g., in `libcore/fmt/float.rs`). We should make
// a final decision about the rules before stabilization.
#[unstable(feature = "maybe_uninit", issue = "53491")]
#[unstable(feature = "maybe_uninit_ref", issue = "53491")]
#[inline(always)]
pub unsafe fn get_mut(&mut self) -> &mut T {
&mut *self.value
}
/// Gets a pointer to the contained value. Reading from this pointer or turning it
/// into a reference will be undefined behavior unless the `MaybeUninit` is initialized.
#[unstable(feature = "maybe_uninit", issue = "53491")]
#[inline(always)]
pub fn as_ptr(&self) -> *const T {
unsafe { &*self.value as *const T }
}
/// Get sa mutable pointer to the contained value. Reading from this pointer or turning it
/// into a reference will be undefined behavior unless the `MaybeUninit` is initialized.
#[unstable(feature = "maybe_uninit", issue = "53491")]
#[inline(always)]
pub fn as_mut_ptr(&mut self) -> *mut T {
unsafe { &mut *self.value as *mut T }
}
/// Gets a pointer to the first element of the array.
#[unstable(feature = "maybe_uninit", issue = "53491")]
#[unstable(feature = "maybe_uninit_slice", issue = "53491")]
#[inline(always)]
pub fn first_ptr(this: &[MaybeUninit<T>]) -> *const T {
this as *const [MaybeUninit<T>] as *const T
}
/// Gets a mutable pointer to the first element of the array.
#[unstable(feature = "maybe_uninit", issue = "53491")]
#[unstable(feature = "maybe_uninit_slice", issue = "53491")]
#[inline(always)]
pub fn first_ptr_mut(this: &mut [MaybeUninit<T>]) -> *mut T {
this as *mut [MaybeUninit<T>] as *mut T