Skip to content

Commit

Permalink
Rollup merge of rust-lang#100861 - RalfJung:const-ice, r=oli-obk
Browse files Browse the repository at this point in the history
fix ICE with extra-const-ub-checks

Fixes rust-lang#100771
  • Loading branch information
matthiaskrgr authored Aug 23, 2022
2 parents 3d201a1 + d7ee421 commit cb9ab80
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 7 deletions.
22 changes: 18 additions & 4 deletions compiler/rustc_const_eval/src/const_eval/eval_queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
),
)
}

Expand Down Expand Up @@ -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, \
Expand Down Expand Up @@ -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);
Expand Down
12 changes: 10 additions & 2 deletions compiler/rustc_const_eval/src/const_eval/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}
}
Expand Down Expand Up @@ -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)]
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_const_eval/src/might_permit_raw_init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
20 changes: 20 additions & 0 deletions src/test/ui/consts/extra-const-ub/issue-100771.rs
Original file line number Diff line number Diff line change
@@ -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!(),
}
}

0 comments on commit cb9ab80

Please sign in to comment.