about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGurinder Singh <frederick.the.fool@gmail.com>2024-02-26 15:22:22 +0530
committerGurinder Singh <frederick.the.fool@gmail.com>2024-02-26 15:22:22 +0530
commit633c92cd6de9e269b9c5b10f341fc10280503f0c (patch)
treed9635cef700249491198ee0482fcbb500ac5c537
parent0250ef2571185b05701ed9d74fc904c17508a397 (diff)
Do not const pop unions
as they can made to produce values whose types don't
match their underlying layout types which can lead to
ICEs on eval
-rw-r--r--compiler/rustc_mir_transform/src/known_panics_lint.rs40
-rw-r--r--tests/ui/lint/ice-unions-known-panics-lint-issue-121534.rs21
2 files changed, 47 insertions, 14 deletions
diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs
index a9cd688c315..7cab6650994 100644
--- a/compiler/rustc_mir_transform/src/known_panics_lint.rs
+++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs
@@ -585,20 +585,32 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                 val.into()
             }
 
-            Aggregate(ref kind, ref fields) => Value::Aggregate {
-                fields: fields
-                    .iter()
-                    .map(|field| self.eval_operand(field).map_or(Value::Uninit, Value::Immediate))
-                    .collect(),
-                variant: match **kind {
-                    AggregateKind::Adt(_, variant, _, _, _) => variant,
-                    AggregateKind::Array(_)
-                    | AggregateKind::Tuple
-                    | AggregateKind::Closure(_, _)
-                    | AggregateKind::Coroutine(_, _)
-                    | AggregateKind::CoroutineClosure(_, _) => VariantIdx::new(0),
-                },
-            },
+            Aggregate(ref kind, ref fields) => {
+                // Do not const pop union fields as they can be
+                // made to produce values that don't match their
+                // underlying layout's type (see ICE #121534).
+                // If the last element of the `Adt` tuple
+                // is `Some` it indicates the ADT is a union
+                if let AggregateKind::Adt(_, _, _, _, Some(_)) = **kind {
+                    return None;
+                };
+                Value::Aggregate {
+                    fields: fields
+                        .iter()
+                        .map(|field| {
+                            self.eval_operand(field).map_or(Value::Uninit, Value::Immediate)
+                        })
+                        .collect(),
+                    variant: match **kind {
+                        AggregateKind::Adt(_, variant, _, _, _) => variant,
+                        AggregateKind::Array(_)
+                        | AggregateKind::Tuple
+                        | AggregateKind::Closure(_, _)
+                        | AggregateKind::Coroutine(_, _)
+                        | AggregateKind::CoroutineClosure(_, _) => VariantIdx::new(0),
+                    },
+                }
+            }
 
             Repeat(ref op, n) => {
                 trace!(?op, ?n);
diff --git a/tests/ui/lint/ice-unions-known-panics-lint-issue-121534.rs b/tests/ui/lint/ice-unions-known-panics-lint-issue-121534.rs
new file mode 100644
index 00000000000..9fadb828b3d
--- /dev/null
+++ b/tests/ui/lint/ice-unions-known-panics-lint-issue-121534.rs
@@ -0,0 +1,21 @@
+// Regression test for #121534
+// Tests that no ICE occurs in KnownPanicsLint when it
+// evaluates an operation whose operands have different
+// layout types even though they have the same type.
+// This situation can be contrived through the use of
+// unions as in this test
+
+//@ build-pass
+union Union {
+    u32_field: u32,
+    i32_field: i32,
+}
+
+pub fn main() {
+    let u32_variant = Union { u32_field: 2 };
+    let i32_variant = Union { i32_field: 3 };
+    let a = unsafe { u32_variant.u32_field };
+    let b = unsafe { i32_variant.u32_field };
+
+    let _diff = a - b;
+}