From 8bd80e25f0bdb7a3282fecee148afed966067f1e Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Wed, 2 Dec 2020 02:32:10 +0100 Subject: [PATCH] Make some of MaybeUninit's methods const --- .../rustc_mir/src/interpret/intrinsics.rs | 24 +++++++++++++++++++ library/core/src/intrinsics.rs | 1 + library/core/src/lib.rs | 1 + library/core/src/mem/maybe_uninit.rs | 7 ++++-- 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir/src/interpret/intrinsics.rs b/compiler/rustc_mir/src/interpret/intrinsics.rs index f666a89ca56d..c751f4f7eb6c 100644 --- a/compiler/rustc_mir/src/interpret/intrinsics.rs +++ b/compiler/rustc_mir/src/interpret/intrinsics.rs @@ -407,6 +407,30 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { sym::transmute => { self.copy_op_transmute(args[0], dest)?; } + sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => { + let ty = instance.substs.type_at(0); + let layout = self.layout_of(ty)?; + + if layout.abi.is_uninhabited() { + throw_ub_format!("attempted to instantiate uninhabited type `{}`", ty); + } + if intrinsic_name == sym::assert_zero_valid + && !layout.might_permit_raw_init(self, /*zero:*/ true).unwrap() + { + throw_ub_format!( + "attempted to zero-initialize type `{}`, which is invalid", + ty + ); + } + if intrinsic_name == sym::assert_uninit_valid + && !layout.might_permit_raw_init(self, /*zero:*/ false).unwrap() + { + throw_ub_format!( + "attempted to leave type `{}` uninitialized, which is invalid", + ty + ); + } + } sym::simd_insert => { let index = u64::from(self.read_scalar(args[1])?.to_u32()?); let elem = args[2]; diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 1a588b314c4f..c0fcfb3a1395 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -815,6 +815,7 @@ extern "rust-intrinsic" { /// This will statically either panic, or do nothing. /// /// This intrinsic does not have a stable counterpart. + #[rustc_const_unstable(feature = "const_maybe_assume_init", issue = "none")] pub fn assert_inhabited(); /// A guard for unsafe functions that cannot ever be executed if `T` does not permit diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index e3b004be39af..5d56a22bfa53 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -100,6 +100,7 @@ #![feature(const_type_name)] #![feature(const_likely)] #![feature(const_unreachable_unchecked)] +#![feature(const_maybe_assume_init)] #![feature(custom_inner_attributes)] #![feature(decl_macro)] #![feature(doc_cfg)] diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 1924720b949f..cb32c909717a 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -314,8 +314,10 @@ impl MaybeUninit { /// let data = read(&mut buf); /// ``` #[unstable(feature = "maybe_uninit_uninit_array", issue = "none")] + #[rustc_const_unstable(feature = "const_maybe_assume_init", issue = "none")] + #[rustc_allow_const_fn_unstable(const_maybe_assume_init)] #[inline(always)] - pub fn uninit_array() -> [Self; LEN] { + pub const fn uninit_array() -> [Self; LEN] { // SAFETY: An uninitialized `[MaybeUninit<_>; LEN]` is valid. unsafe { MaybeUninit::<[MaybeUninit; LEN]>::uninit().assume_init() } } @@ -503,9 +505,10 @@ impl MaybeUninit { /// // `x` had not been initialized yet, so this last line caused undefined behavior. ⚠️ /// ``` #[stable(feature = "maybe_uninit", since = "1.36.0")] + #[rustc_const_unstable(feature = "const_maybe_assume_init", issue = "none")] #[inline(always)] #[rustc_diagnostic_item = "assume_init"] - pub unsafe fn assume_init(self) -> T { + pub const unsafe fn assume_init(self) -> T { // SAFETY: the caller must guarantee that `self` is initialized. // This also means that `self` must be a `value` variant. unsafe {