interpret: sanity-check that required_consts captures all consts that can fail
This commit is contained in:
parent
b2b617a88e
commit
bf021ea625
7 changed files with 62 additions and 34 deletions
|
@ -46,6 +46,12 @@ impl<'mir, 'tcx: 'mir> interpret::Machine<'mir, 'tcx> for DummyMachine {
|
|||
type MemoryKind = !;
|
||||
const PANIC_ON_ALLOC_FAIL: bool = true;
|
||||
|
||||
#[inline(always)]
|
||||
fn all_required_consts_are_checked(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
|
||||
// We want to just eval random consts in the program, so `eval_mir_const` can fail.
|
||||
false
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn enforce_alignment(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
|
||||
false // no reason to enforce alignment
|
||||
|
|
|
@ -375,6 +375,20 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
|||
|
||||
const PANIC_ON_ALLOC_FAIL: bool = false; // will be raised as a proper error
|
||||
|
||||
#[inline]
|
||||
fn all_required_consts_are_checked(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
|
||||
// Generally we expect required_consts to be properly filled, except for promoteds where
|
||||
// storing these consts shows up negatively in benchmarks. A promoted can only be relevant
|
||||
// if its parent MIR is relevant, and the consts in the promoted will be in the parent's
|
||||
// `required_consts`, so we are still sure to catch any const-eval bugs, just a bit less
|
||||
// directly.
|
||||
if ecx.frame_idx() == 0 && ecx.frame().body.source.promoted.is_some() {
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
|
||||
matches!(ecx.machine.check_alignment, CheckAlignment::Error)
|
||||
|
|
|
@ -822,15 +822,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
self.stack_mut().push(frame);
|
||||
|
||||
// Make sure all the constants required by this frame evaluate successfully (post-monomorphization check).
|
||||
if M::POST_MONO_CHECKS {
|
||||
for &const_ in &body.required_consts {
|
||||
let c = self
|
||||
.instantiate_from_current_frame_and_normalize_erasing_regions(const_.const_)?;
|
||||
c.eval(*self.tcx, self.param_env, const_.span).map_err(|err| {
|
||||
err.emit_note(*self.tcx);
|
||||
err
|
||||
})?;
|
||||
}
|
||||
for &const_ in &body.required_consts {
|
||||
let c =
|
||||
self.instantiate_from_current_frame_and_normalize_erasing_regions(const_.const_)?;
|
||||
c.eval(*self.tcx, self.param_env, const_.span).map_err(|err| {
|
||||
err.emit_note(*self.tcx);
|
||||
err
|
||||
})?;
|
||||
}
|
||||
|
||||
// done
|
||||
|
@ -1181,8 +1179,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
|
||||
M::eval_mir_constant(self, *val, span, layout, |ecx, val, span, layout| {
|
||||
let const_val = val.eval(*ecx.tcx, ecx.param_env, span).map_err(|err| {
|
||||
// FIXME: somehow this is reachable even when POST_MONO_CHECKS is on.
|
||||
// Are we not always populating `required_consts`?
|
||||
if M::all_required_consts_are_checked(self)
|
||||
&& !matches!(err, ErrorHandled::TooGeneric(..))
|
||||
{
|
||||
// Looks like the const is not captued by `required_consts`, that's bad.
|
||||
bug!("interpret const eval failure of {val:?} which is not in required_consts");
|
||||
}
|
||||
err.emit_note(*ecx.tcx);
|
||||
err
|
||||
})?;
|
||||
|
|
|
@ -140,8 +140,9 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
|||
/// Should the machine panic on allocation failures?
|
||||
const PANIC_ON_ALLOC_FAIL: bool;
|
||||
|
||||
/// Should post-monomorphization checks be run when a stack frame is pushed?
|
||||
const POST_MONO_CHECKS: bool = true;
|
||||
/// Determines whether `eval_mir_constant` can never fail because all required consts have
|
||||
/// already been checked before.
|
||||
fn all_required_consts_are_checked(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
|
||||
|
||||
/// Whether memory accesses should be alignment-checked.
|
||||
fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue