about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2022-08-21 20:00:38 -0400
committerRalf Jung <post@ralfj.de>2022-08-21 20:00:38 -0400
commitd7ee421870f8937fe351b4143036c2730129757a (patch)
treea9adfb7936e46b91ce9031392d5edcd353dde08b
parentc0941dfb5a7d07ef2d70cc54d319669d9d6f6c01 (diff)
downloadrust-d7ee421870f8937fe351b4143036c2730129757a.tar.gz
rust-d7ee421870f8937fe351b4143036c2730129757a.zip
fix ICE with extra-const-ub-checks
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs22
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs12
-rw-r--r--compiler/rustc_const_eval/src/might_permit_raw_init.rs6
-rw-r--r--src/test/ui/consts/extra-const-ub/issue-100771.rs20
4 files changed, 53 insertions, 7 deletions
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index 936044fbe24..5cfa63bd105 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -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);
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 684877cae76..f24b19089c1 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -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)]
diff --git a/compiler/rustc_const_eval/src/might_permit_raw_init.rs b/compiler/rustc_const_eval/src/might_permit_raw_init.rs
index f971c2238c7..37ffa19ccd6 100644
--- a/compiler/rustc_const_eval/src/might_permit_raw_init.rs
+++ b/compiler/rustc_const_eval/src/might_permit_raw_init.rs
@@ -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);
 
diff --git a/src/test/ui/consts/extra-const-ub/issue-100771.rs b/src/test/ui/consts/extra-const-ub/issue-100771.rs
new file mode 100644
index 00000000000..a3296032841
--- /dev/null
+++ b/src/test/ui/consts/extra-const-ub/issue-100771.rs
@@ -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!(),
+    }
+}