use ops::{Deref, DerefMut};
#[stable(feature = "rust1", since = "1.0.0")]
+#[doc(inline)]
pub use intrinsics::transmute;
/// Takes ownership and "forgets" about the value **without running its destructor**.
/// assert_eq!(0, x);
/// ```
#[inline]
-#[rustc_deprecated(since = "2.0.0", reason = "use `mem::MaybeUninit::zeroed` instead")]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn zeroed<T>() -> T {
- #[cfg(not(stage0))]
intrinsics::panic_if_uninhabited::<T>();
intrinsics::init()
}
#[rustc_deprecated(since = "2.0.0", reason = "use `mem::MaybeUninit::uninitialized` instead")]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn uninitialized<T>() -> T {
- #[cfg(not(stage0))]
intrinsics::panic_if_uninhabited::<T>();
intrinsics::uninit()
}
/// Disposes of a value.
///
-/// While this does call the argument's implementation of [`Drop`][drop],
-/// it will not release any borrows, as borrows are based on lexical scope.
+/// This does call the argument's implementation of [`Drop`][drop].
///
/// This effectively does nothing for types which implement `Copy`, e.g.
/// integers. Such values are copied and _then_ moved into the function, so the
/// drop(v); // explicitly drop the vector
/// ```
///
-/// Borrows are based on lexical scope, so this produces an error:
-///
-/// ```compile_fail,E0502
-/// let mut v = vec![1, 2, 3];
-/// let x = &v[0];
-///
-/// drop(x); // explicitly drop the reference, but the borrow still exists
-///
-/// v.push(4); // error: cannot borrow `v` as mutable because it is also
-/// // borrowed as immutable
-/// ```
-///
-/// An inner scope is needed to fix this:
-///
-/// ```
-/// let mut v = vec![1, 2, 3];
-///
-/// {
-/// let x = &v[0];
-///
-/// drop(x); // this is now redundant, as `x` is going out of scope anyway
-/// }
-///
-/// v.push(4); // no problems
-/// ```
-///
/// Since [`RefCell`] enforces the borrow rules at runtime, `drop` can
/// release a [`RefCell`] borrow:
///
}
}
-/// A newtype to construct uninitialized instances of `T`
+/// A newtype to construct uninitialized instances of `T`.
+///
+/// The compiler, in general, assumes that variables are properly initialized
+/// at their respective type. For example, a variable of reference type must
+/// be aligned and non-NULL. This is an invariant that must *always* be upheld,
+/// even in unsafe code. As a consequence, 0-initializing a variable of reference
+/// type causes instantaneous undefined behavior, no matter whether that reference
+/// ever gets used to access memory:
+/// ```rust,no_run
+/// use std::mem;
+///
+/// let x: &i32 = unsafe { mem::zeroed() }; // 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 0-initializing it) causes the same
+/// issue: after all, the initial value of the variable might just happen to be
+/// one that violates the invariant.
+///
+/// `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*
+/// be initialized:
+/// ```rust
+/// #![feature(maybe_uninit)]
+/// use std::mem::MaybeUninit;
+///
+/// // Create an explicitly uninitialized reference.
+/// let mut x = MaybeUninit::<&i32>::uninitialized();
+/// // Set it to a valid value.
+/// x.set(&0);
+/// // Extract the initialized data -- this is only allowed *after* properly
+/// // initializing `x`!
+/// let x = unsafe { x.into_initialized() };
+/// ```
+/// The compiler then knows to not optimize this code.
#[allow(missing_debug_implementations)]
#[unstable(feature = "maybe_uninit", issue = "53491")]
// NOTE after stabilizing `MaybeUninit` proceed to deprecate `mem::{uninitialized,zeroed}`
}
/// Set the value of the `MaybeUninit`. This overwrites any previous value without dropping it.
+ /// For your convenience, this also returns a mutable reference to the (now
+ /// safely initialized) content of `self`.
#[unstable(feature = "maybe_uninit", issue = "53491")]
#[inline(always)]
- pub fn set(&mut self, val: T) {
+ pub fn set(&mut self, val: T) -> &mut T {
unsafe {
self.value = ManuallyDrop::new(val);
+ self.get_mut()
}
}
/// state, otherwise this will immediately cause undefined behavior.
#[unstable(feature = "maybe_uninit", issue = "53491")]
#[inline(always)]
- pub unsafe fn into_inner(self) -> T {
- #[cfg(not(stage0))]
+ pub unsafe fn into_initialized(self) -> T {
intrinsics::panic_if_uninhabited::<T>();
ManuallyDrop::into_inner(self.value)
}
+ /// Deprecated alternative to `into_initialized`. Will never get stabilized.
+ /// Exists only to transition stdsimd to `into_initialized`.
+ #[inline(always)]
+ #[allow(unused)]
+ pub(crate) unsafe fn into_inner(self) -> T {
+ self.into_initialized()
+ }
+
/// Get a reference to the contained value.
///
/// # Unsafety
&mut *self.value
}
- /// Get a pointer to the contained value. Reading from this pointer will be undefined
- /// behavior unless the `MaybeUninit` is initialized.
+ /// Get 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 a mutable pointer to the contained value. Reading from this pointer will be undefined
- /// behavior unless the `MaybeUninit` is initialized.
+ /// Get 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 }
}
+
+ /// Get a pointer to the first element of the array.
+ #[unstable(feature = "maybe_uninit", issue = "53491")]
+ #[inline(always)]
+ pub fn first_ptr(this: &[MaybeUninit<T>]) -> *const T {
+ this as *const [MaybeUninit<T>] as *const T
+ }
+
+ /// Get a mutable pointer to the first element of the array.
+ #[unstable(feature = "maybe_uninit", issue = "53491")]
+ #[inline(always)]
+ pub fn first_ptr_mut(this: &mut [MaybeUninit<T>]) -> *mut T {
+ this as *mut [MaybeUninit<T>] as *mut T
+ }
}