Skip to content

Commit a940c68

Browse files
authoredNov 30, 2021
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 #90896 (meaning stable `const fn` can call it), so do the same with these other intrinsics. Cc ```@rust-lang/wg-const-eval```
2 parents ae1badb + 6c3c3e0 commit a940c68

File tree

6 files changed

+88
-29
lines changed

6 files changed

+88
-29
lines changed
 

‎compiler/rustc_const_eval/src/interpret/intrinsics.rs

+25-1
Original file line numberDiff line numberDiff line change
@@ -394,10 +394,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
394394
sym::transmute => {
395395
self.copy_op_transmute(&args[0], dest)?;
396396
}
397-
sym::assert_inhabited => {
397+
sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => {
398398
let ty = instance.substs.type_at(0);
399399
let layout = self.layout_of(ty)?;
400400

401+
// For *all* intrinsics we first check `is_uninhabited` to give a more specific
402+
// error message.
401403
if layout.abi.is_uninhabited() {
402404
// The run-time intrinsic panics just to get a good backtrace; here we abort
403405
// 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> {
409411
),
410412
)?;
411413
}
414+
if intrinsic_name == sym::assert_zero_valid
415+
&& !layout.might_permit_raw_init(self, /*zero:*/ true)
416+
{
417+
M::abort(
418+
self,
419+
format!(
420+
"aborted execution: attempted to zero-initialize type `{}`, which is invalid",
421+
ty
422+
),
423+
)?;
424+
}
425+
if intrinsic_name == sym::assert_uninit_valid
426+
&& !layout.might_permit_raw_init(self, /*zero:*/ false)
427+
{
428+
M::abort(
429+
self,
430+
format!(
431+
"aborted execution: attempted to leave type `{}` uninitialized, which is invalid",
432+
ty
433+
),
434+
)?;
435+
}
412436
}
413437
sym::simd_insert => {
414438
let index = u64::from(self.read_scalar(&args[1])?.to_u32()?);

‎library/core/src/intrinsics.rs

+2
Original file line numberDiff line numberDiff line change
@@ -860,12 +860,14 @@ extern "rust-intrinsic" {
860860
/// zero-initialization: This will statically either panic, or do nothing.
861861
///
862862
/// This intrinsic does not have a stable counterpart.
863+
#[rustc_const_unstable(feature = "const_assert_type2", issue = "none")]
863864
pub fn assert_zero_valid<T>();
864865

865866
/// A guard for unsafe functions that cannot ever be executed if `T` has invalid
866867
/// bit patterns: This will statically either panic, or do nothing.
867868
///
868869
/// This intrinsic does not have a stable counterpart.
870+
#[rustc_const_unstable(feature = "const_assert_type2", issue = "none")]
869871
pub fn assert_uninit_valid<T>();
870872

871873
/// Gets a reference to a static `Location` indicating where it was called.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// error-pattern: any use of this value will cause an error
2+
3+
#![feature(never_type)]
4+
#![feature(const_maybe_uninit_assume_init, const_assert_type2)]
5+
#![feature(core_intrinsics)]
6+
7+
use std::intrinsics;
8+
9+
#[allow(invalid_value)]
10+
fn main() {
11+
use std::mem::MaybeUninit;
12+
13+
const _BAD1: () = unsafe {
14+
MaybeUninit::<!>::uninit().assume_init();
15+
};
16+
const _BAD2: () = unsafe {
17+
intrinsics::assert_uninit_valid::<bool>();
18+
};
19+
const _BAD3: () = unsafe {
20+
intrinsics::assert_zero_valid::<&'static i32>();
21+
};
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
error: any use of this value will cause an error
2+
--> $DIR/assert-type-intrinsics.rs:14:9
3+
|
4+
LL | / const _BAD1: () = unsafe {
5+
LL | | MaybeUninit::<!>::uninit().assume_init();
6+
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!`
7+
LL | | };
8+
| |______-
9+
|
10+
= note: `#[deny(const_err)]` on by default
11+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
12+
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
13+
14+
error: any use of this value will cause an error
15+
--> $DIR/assert-type-intrinsics.rs:17:9
16+
|
17+
LL | / const _BAD2: () = unsafe {
18+
LL | | intrinsics::assert_uninit_valid::<bool>();
19+
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to leave type `bool` uninitialized, which is invalid
20+
LL | | };
21+
| |______-
22+
|
23+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
24+
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
25+
26+
error: any use of this value will cause an error
27+
--> $DIR/assert-type-intrinsics.rs:20:9
28+
|
29+
LL | / const _BAD3: () = unsafe {
30+
LL | | intrinsics::assert_zero_valid::<&'static i32>();
31+
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to zero-initialize type `&i32`, which is invalid
32+
LL | | };
33+
| |______-
34+
|
35+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
36+
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
37+
38+
error: aborting due to 3 previous errors
39+

‎src/test/ui/consts/assume-type-intrinsics.rs

-13
This file was deleted.

‎src/test/ui/consts/assume-type-intrinsics.stderr

-15
This file was deleted.

0 commit comments

Comments
 (0)
Please sign in to comment.