Rollup merge of #91323 - RalfJung:assert-type, r=oli-obk

CTFE: support assert_zero_valid and assert_uninit_valid

This ensures the implementation of all three type-based assert_ intrinsics remains consistent in Miri.

`assert_inhabited` recently got stabilized in https://github.com/rust-lang/rust/pull/90896 (meaning stable `const fn` can call it), so do the same with these other intrinsics.

Cc ```@rust-lang/wg-const-eval```
This commit is contained in:
Yuki Okushi 2021-11-30 17:29:09 +09:00 committed by GitHub
commit a940c68035
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 88 additions and 29 deletions

View File

@ -394,10 +394,12 @@ 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_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => {
let ty = instance.substs.type_at(0);
let layout = self.layout_of(ty)?;
// For *all* intrinsics we first check `is_uninhabited` to give a more specific
// error message.
if layout.abi.is_uninhabited() {
// The run-time intrinsic panics just to get a good backtrace; here we abort
// since there is no problem showing a backtrace even for aborts.
@ -409,6 +411,28 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
),
)?;
}
if intrinsic_name == sym::assert_zero_valid
&& !layout.might_permit_raw_init(self, /*zero:*/ true)
{
M::abort(
self,
format!(
"aborted execution: attempted to zero-initialize type `{}`, which is invalid",
ty
),
)?;
}
if intrinsic_name == sym::assert_uninit_valid
&& !layout.might_permit_raw_init(self, /*zero:*/ false)
{
M::abort(
self,
format!(
"aborted execution: attempted to leave type `{}` uninitialized, which is invalid",
ty
),
)?;
}
}
sym::simd_insert => {
let index = u64::from(self.read_scalar(&args[1])?.to_u32()?);

View File

@ -860,12 +860,14 @@ extern "rust-intrinsic" {
/// zero-initialization: This will statically either panic, or do nothing.
///
/// This intrinsic does not have a stable counterpart.
#[rustc_const_unstable(feature = "const_assert_type2", issue = "none")]
pub fn assert_zero_valid<T>();
/// A guard for unsafe functions that cannot ever be executed if `T` has invalid
/// bit patterns: This will statically either panic, or do nothing.
///
/// This intrinsic does not have a stable counterpart.
#[rustc_const_unstable(feature = "const_assert_type2", issue = "none")]
pub fn assert_uninit_valid<T>();
/// Gets a reference to a static `Location` indicating where it was called.

View File

@ -0,0 +1,22 @@
// error-pattern: any use of this value will cause an error
#![feature(never_type)]
#![feature(const_maybe_uninit_assume_init, const_assert_type2)]
#![feature(core_intrinsics)]
use std::intrinsics;
#[allow(invalid_value)]
fn main() {
use std::mem::MaybeUninit;
const _BAD1: () = unsafe {
MaybeUninit::<!>::uninit().assume_init();
};
const _BAD2: () = unsafe {
intrinsics::assert_uninit_valid::<bool>();
};
const _BAD3: () = unsafe {
intrinsics::assert_zero_valid::<&'static i32>();
};
}

View File

@ -0,0 +1,39 @@
error: any use of this value will cause an error
--> $DIR/assert-type-intrinsics.rs:14:9
|
LL | / const _BAD1: () = unsafe {
LL | | MaybeUninit::<!>::uninit().assume_init();
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!`
LL | | };
| |______-
|
= note: `#[deny(const_err)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
error: any use of this value will cause an error
--> $DIR/assert-type-intrinsics.rs:17:9
|
LL | / const _BAD2: () = unsafe {
LL | | intrinsics::assert_uninit_valid::<bool>();
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to leave type `bool` uninitialized, which is invalid
LL | | };
| |______-
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
error: any use of this value will cause an error
--> $DIR/assert-type-intrinsics.rs:20:9
|
LL | / const _BAD3: () = unsafe {
LL | | intrinsics::assert_zero_valid::<&'static i32>();
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to zero-initialize type `&i32`, which is invalid
LL | | };
| |______-
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
error: aborting due to 3 previous errors

View File

@ -1,13 +0,0 @@
// error-pattern: any use of this value will cause an error
#![feature(never_type)]
#![feature(const_maybe_uninit_assume_init)]
#[allow(invalid_value)]
fn main() {
use std::mem::MaybeUninit;
const _BAD: () = unsafe {
MaybeUninit::<!>::uninit().assume_init();
};
}

View File

@ -1,15 +0,0 @@
error: any use of this value will cause an error
--> $DIR/assume-type-intrinsics.rs:11:9
|
LL | / const _BAD: () = unsafe {
LL | | MaybeUninit::<!>::uninit().assume_init();
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!`
LL | | };
| |______-
|
= note: `#[deny(const_err)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
error: aborting due to previous error