From 826bc3648af1596413de0e7dcfe5f32665619608 Mon Sep 17 00:00:00 2001 From: CoffeeBlend Date: Fri, 1 Jan 2021 22:03:14 +0100 Subject: [PATCH] Implement MaybeUninit::array_assume_init --- library/core/src/mem/maybe_uninit.rs | 49 ++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index b2a4d897eede..b157eec24b41 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -804,6 +804,55 @@ impl MaybeUninit { } } + /// Extracts the values from an array of `MaybeUninit` containers. + /// + /// # Safety + /// + /// It is up to the caller to guarantee that all elements of the array are + /// in an initialized state. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_uninit_array)] + /// #![feature(maybe_uninit_array_assume_init)] + /// use std::mem::MaybeUninit; + /// + /// let mut array: [MaybeUninit; 3] = MaybeUninit::uninit_array(); + /// array[0] = MaybeUninit::new(0); + /// array[1] = MaybeUninit::new(1); + /// array[2] = MaybeUninit::new(2); + /// + /// // SAFETY: Now safe as we initialised all elements + /// let array = unsafe { + /// MaybeUninit::array_assume_init(array) + /// }; + /// + /// assert_eq!(array, [0, 1, 2]); + /// ``` + #[unstable(feature = "maybe_uninit_array_assume_init", issue = "none")] + #[inline(always)] + pub unsafe fn array_assume_init(array: [Self; N]) -> [T; N] { + // Convert using a union because mem::transmute does not support const_generics + union ArrayInit { + maybe_uninit: ManuallyDrop<[MaybeUninit; N]>, + init: ManuallyDrop<[T; N]>, + } + + // SAFETY: + // * The caller guarantees that all elements of the array are initialized, + // * `MaybeUninit` and T are guaranteed to have the same layout, + // Therefore the conversion is safe + unsafe { + intrinsics::assert_inhabited::(); + + let array = ArrayInit { + maybe_uninit: ManuallyDrop::new(array), + }; + ManuallyDrop::into_inner(array.init) + } + } + /// Assuming all the elements are initialized, get a slice to them. /// /// # Safety