CTFE: support assert_zero_valid and assert_uninit_valid

This commit is contained in:
Ralf Jung 2021-11-28 13:00:37 -05:00
parent 58f9efd36d
commit 6c3c3e0952
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()?);