Skip to content

Commit f5fcac9

Browse files
authored
Rollup merge of #100861 - RalfJung:const-ice, r=oli-obk
fix ICE with extra-const-ub-checks Fixes #100771
2 parents 21d8f48 + d7ee421 commit f5fcac9

File tree

4 files changed

+53
-7
lines changed

4 files changed

+53
-7
lines changed

compiler/rustc_const_eval/src/const_eval/eval_queries.rs

+18-4
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
8181
}
8282

8383
/// The `InterpCx` is only meant to be used to do field and index projections into constants for
84-
/// `simd_shuffle` and const patterns in match arms.
84+
/// `simd_shuffle` and const patterns in match arms. It never performs alignment checks.
8585
///
8686
/// The function containing the `match` that is currently being analyzed may have generic bounds
8787
/// 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>(
9898
tcx,
9999
root_span,
100100
param_env,
101-
CompileTimeInterpreter::new(tcx.const_eval_limit(), can_access_statics),
101+
CompileTimeInterpreter::new(
102+
tcx.const_eval_limit(),
103+
can_access_statics,
104+
/*check_alignment:*/ false,
105+
),
102106
)
103107
}
104108

@@ -203,7 +207,13 @@ pub(crate) fn turn_into_const_value<'tcx>(
203207
let cid = key.value;
204208
let def_id = cid.instance.def.def_id();
205209
let is_static = tcx.is_static(def_id);
206-
let ecx = mk_eval_cx(tcx, tcx.def_span(key.value.instance.def_id()), key.param_env, is_static);
210+
// This is just accessing an already computed constant, so no need to check alginment here.
211+
let ecx = mk_eval_cx(
212+
tcx,
213+
tcx.def_span(key.value.instance.def_id()),
214+
key.param_env,
215+
/*can_access_statics:*/ is_static,
216+
);
207217

208218
let mplace = ecx.raw_const_to_mplace(constant).expect(
209219
"can only fail if layout computation failed, \
@@ -300,7 +310,11 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
300310
key.param_env,
301311
// Statics (and promoteds inside statics) may access other statics, because unlike consts
302312
// they do not have to behave "as if" they were evaluated at runtime.
303-
CompileTimeInterpreter::new(tcx.const_eval_limit(), /*can_access_statics:*/ is_static),
313+
CompileTimeInterpreter::new(
314+
tcx.const_eval_limit(),
315+
/*can_access_statics:*/ is_static,
316+
/*check_alignment:*/ tcx.sess.opts.unstable_opts.extra_const_ub_checks,
317+
),
304318
);
305319

306320
let res = ecx.load_mir(cid.instance.def, cid.promoted);

compiler/rustc_const_eval/src/const_eval/machine.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -101,14 +101,22 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> {
101101
/// * Pointers to allocations inside of statics can never leak outside, to a non-static global.
102102
/// This boolean here controls the second part.
103103
pub(super) can_access_statics: bool,
104+
105+
/// Whether to check alignment during evaluation.
106+
check_alignment: bool,
104107
}
105108

106109
impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> {
107-
pub(crate) fn new(const_eval_limit: Limit, can_access_statics: bool) -> Self {
110+
pub(crate) fn new(
111+
const_eval_limit: Limit,
112+
can_access_statics: bool,
113+
check_alignment: bool,
114+
) -> Self {
108115
CompileTimeInterpreter {
109116
steps_remaining: const_eval_limit.0,
110117
stack: Vec::new(),
111118
can_access_statics,
119+
check_alignment,
112120
}
113121
}
114122
}
@@ -238,7 +246,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
238246

239247
#[inline(always)]
240248
fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
241-
ecx.tcx.sess.opts.unstable_opts.extra_const_ub_checks
249+
ecx.machine.check_alignment
242250
}
243251

244252
#[inline(always)]

compiler/rustc_const_eval/src/might_permit_raw_init.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ pub fn might_permit_raw_init<'tcx>(
1313
let strict = tcx.sess.opts.unstable_opts.strict_init_checks;
1414

1515
if strict {
16-
let machine = CompileTimeInterpreter::new(Limit::new(0), false);
16+
let machine = CompileTimeInterpreter::new(
17+
Limit::new(0),
18+
/*can_access_statics:*/ false,
19+
/*check_alignment:*/ true,
20+
);
1721

1822
let mut cx = InterpCx::new(tcx, rustc_span::DUMMY_SP, ParamEnv::reveal_all(), machine);
1923

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// check-pass
2+
// compile-flags: -Zextra-const-ub-checks
3+
4+
#[derive(PartialEq, Eq, Copy, Clone)]
5+
#[repr(packed)]
6+
struct Foo {
7+
field: (i64, u32, u32, u32),
8+
}
9+
10+
const FOO: Foo = Foo {
11+
field: (5, 6, 7, 8),
12+
};
13+
14+
fn main() {
15+
match FOO {
16+
Foo { field: (5, 6, 7, 8) } => {},
17+
FOO => unreachable!(),
18+
_ => unreachable!(),
19+
}
20+
}

0 commit comments

Comments
 (0)