fix ICE with extra-const-ub-checks

This commit is contained in:
Ralf Jung 2022-08-21 20:00:38 -04:00
parent c0941dfb5a
commit d7ee421870
4 changed files with 53 additions and 7 deletions

View File

@ -81,7 +81,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
}
/// The `InterpCx` is only meant to be used to do field and index projections into constants for
/// `simd_shuffle` and const patterns in match arms.
/// `simd_shuffle` and const patterns in match arms. It never performs alignment checks.
///
/// The function containing the `match` that is currently being analyzed may have generic bounds
/// that inform us about the generic bounds of the constant. E.g., using an associated constant
@ -98,7 +98,11 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>(
tcx,
root_span,
param_env,
CompileTimeInterpreter::new(tcx.const_eval_limit(), can_access_statics),
CompileTimeInterpreter::new(
tcx.const_eval_limit(),
can_access_statics,
/*check_alignment:*/ false,
),
)
}
@ -203,7 +207,13 @@ pub(crate) fn turn_into_const_value<'tcx>(
let cid = key.value;
let def_id = cid.instance.def.def_id();
let is_static = tcx.is_static(def_id);
let ecx = mk_eval_cx(tcx, tcx.def_span(key.value.instance.def_id()), key.param_env, is_static);
// This is just accessing an already computed constant, so no need to check alginment here.
let ecx = mk_eval_cx(
tcx,
tcx.def_span(key.value.instance.def_id()),
key.param_env,
/*can_access_statics:*/ is_static,
);
let mplace = ecx.raw_const_to_mplace(constant).expect(
"can only fail if layout computation failed, \
@ -300,7 +310,11 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
key.param_env,
// Statics (and promoteds inside statics) may access other statics, because unlike consts
// they do not have to behave "as if" they were evaluated at runtime.
CompileTimeInterpreter::new(tcx.const_eval_limit(), /*can_access_statics:*/ is_static),
CompileTimeInterpreter::new(
tcx.const_eval_limit(),
/*can_access_statics:*/ is_static,
/*check_alignment:*/ tcx.sess.opts.unstable_opts.extra_const_ub_checks,
),
);
let res = ecx.load_mir(cid.instance.def, cid.promoted);

View File

@ -101,14 +101,22 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> {
/// * Pointers to allocations inside of statics can never leak outside, to a non-static global.
/// This boolean here controls the second part.
pub(super) can_access_statics: bool,
/// Whether to check alignment during evaluation.
check_alignment: bool,
}
impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> {
pub(crate) fn new(const_eval_limit: Limit, can_access_statics: bool) -> Self {
pub(crate) fn new(
const_eval_limit: Limit,
can_access_statics: bool,
check_alignment: bool,
) -> Self {
CompileTimeInterpreter {
steps_remaining: const_eval_limit.0,
stack: Vec::new(),
can_access_statics,
check_alignment,
}
}
}
@ -238,7 +246,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
#[inline(always)]
fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
ecx.tcx.sess.opts.unstable_opts.extra_const_ub_checks
ecx.machine.check_alignment
}
#[inline(always)]

View File

@ -13,7 +13,11 @@ pub fn might_permit_raw_init<'tcx>(
let strict = tcx.sess.opts.unstable_opts.strict_init_checks;
if strict {
let machine = CompileTimeInterpreter::new(Limit::new(0), false);
let machine = CompileTimeInterpreter::new(
Limit::new(0),
/*can_access_statics:*/ false,
/*check_alignment:*/ true,
);
let mut cx = InterpCx::new(tcx, rustc_span::DUMMY_SP, ParamEnv::reveal_all(), machine);

View File

@ -0,0 +1,20 @@
// check-pass
// compile-flags: -Zextra-const-ub-checks
#[derive(PartialEq, Eq, Copy, Clone)]
#[repr(packed)]
struct Foo {
field: (i64, u32, u32, u32),
}
const FOO: Foo = Foo {
field: (5, 6, 7, 8),
};
fn main() {
match FOO {
Foo { field: (5, 6, 7, 8) } => {},
FOO => unreachable!(),
_ => unreachable!(),
}
}