about summary refs log tree commit diff
diff options
context:
space:
mode:
author许杰友 Jieyou Xu (Joe) <39484203+jieyouxu@users.noreply.github.com>2024-04-29 18:03:24 +0100
committerGitHub <noreply@github.com>2024-04-29 18:03:24 +0100
commit43265f5721d09645fc922a6dc71fa5e5b30a48d1 (patch)
treefe7613a832aeb01e6fb10ec06baa00a94562c722
parent0580588ec62182e1387ad36aaad623284f2d409a (diff)
parent254a9fbe86a4a6d3c0481f7924c4b0393e1a230e (diff)
downloadrust-43265f5721d09645fc922a6dc71fa5e5b30a48d1.tar.gz
rust-43265f5721d09645fc922a6dc71fa5e5b30a48d1.zip
Rollup merge of #124504 - gurry:123710-union-ICE, r=oli-obk
Mark unions non-const-propagatable in `KnownPanicsLint` without calling layout

Fixes #123710

The ICE occurs during the layout calculation of the union `InvalidTag` in #123710 because the following assert fails:https://github.com/rust-lang/rust/blob/5fe8b697e729b6eb64841a3905e57da1b47f4ca3/compiler/rustc_abi/src/layout.rs#L289-L292

The layout calculation is invoked by `KnownPanicsLint` when it is trying to figure out which locals it can const prop. Since `KnownPanicsLint` is never actually going to const props unions thanks to PR https://github.com/rust-lang/rust/pull/121628 there's no point calling layout to check if it can. So in this fix I skip the call to layout and just mark the local non-const propagatable if it is a union.
-rw-r--r--compiler/rustc_mir_transform/src/known_panics_lint.rs20
-rw-r--r--tests/crashes/123710.rs17
-rw-r--r--tests/ui/lint/ice-const-prop-unions-known-panics-lint-123710.rs22
-rw-r--r--tests/ui/lint/ice-const-prop-unions-known-panics-lint-123710.stderr29
4 files changed, 64 insertions, 24 deletions
diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs
index b8dbf8a759f..b2030efca8f 100644
--- a/compiler/rustc_mir_transform/src/known_panics_lint.rs
+++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs
@@ -896,13 +896,19 @@ impl CanConstProp {
         };
         for (local, val) in cpv.can_const_prop.iter_enumerated_mut() {
             let ty = body.local_decls[local].ty;
-            match tcx.layout_of(param_env.and(ty)) {
-                Ok(layout) if layout.size < Size::from_bytes(MAX_ALLOC_LIMIT) => {}
-                // Either the layout fails to compute, then we can't use this local anyway
-                // or the local is too large, then we don't want to.
-                _ => {
-                    *val = ConstPropMode::NoPropagation;
-                    continue;
+            if ty.is_union() {
+                // Do not const prop unions as they can
+                // ICE during layout calc
+                *val = ConstPropMode::NoPropagation;
+            } else {
+                match tcx.layout_of(param_env.and(ty)) {
+                    Ok(layout) if layout.size < Size::from_bytes(MAX_ALLOC_LIMIT) => {}
+                    // Either the layout fails to compute, then we can't use this local anyway
+                    // or the local is too large, then we don't want to.
+                    _ => {
+                        *val = ConstPropMode::NoPropagation;
+                        continue;
+                    }
                 }
             }
         }
diff --git a/tests/crashes/123710.rs b/tests/crashes/123710.rs
deleted file mode 100644
index f171fa7cebb..00000000000
--- a/tests/crashes/123710.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-//@ known-bug: #123710
-
-#[repr(packed)]
-#[repr(u32)]
-enum E {
-    A,
-    B,
-    C,
-}
-
-fn main() {
-    union InvalidTag {
-        int: u32,
-        e: E,
-    }
-    let _invalid_tag = InvalidTag { int: 4 };
-}
diff --git a/tests/ui/lint/ice-const-prop-unions-known-panics-lint-123710.rs b/tests/ui/lint/ice-const-prop-unions-known-panics-lint-123710.rs
new file mode 100644
index 00000000000..2b93d0f8a60
--- /dev/null
+++ b/tests/ui/lint/ice-const-prop-unions-known-panics-lint-123710.rs
@@ -0,0 +1,22 @@
+// Regression test for issue 123710.
+// Tests that the we do not ICE in KnownPanicsLint
+// when a union contains an enum with an repr(packed),
+// which is a repr not supported for enums
+
+#[repr(packed)]
+//~^ ERROR attribute should be applied to a struct or union
+#[repr(u32)]
+enum E {
+    A,
+    B,
+    C,
+}
+
+fn main() {
+    union InvalidTag {
+        int: u32,
+        e: E,
+//~^ ERROR field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
+    }
+    let _invalid_tag = InvalidTag { int: 4 };
+}
diff --git a/tests/ui/lint/ice-const-prop-unions-known-panics-lint-123710.stderr b/tests/ui/lint/ice-const-prop-unions-known-panics-lint-123710.stderr
new file mode 100644
index 00000000000..44dde6120e8
--- /dev/null
+++ b/tests/ui/lint/ice-const-prop-unions-known-panics-lint-123710.stderr
@@ -0,0 +1,29 @@
+error[E0517]: attribute should be applied to a struct or union
+  --> $DIR/ice-const-prop-unions-known-panics-lint-123710.rs:6:8
+   |
+LL |   #[repr(packed)]
+   |          ^^^^^^
+...
+LL | / enum E {
+LL | |     A,
+LL | |     B,
+LL | |     C,
+LL | | }
+   | |_- not a struct or union
+
+error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
+  --> $DIR/ice-const-prop-unions-known-panics-lint-123710.rs:18:9
+   |
+LL |         e: E,
+   |         ^^^^
+   |
+   = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>`
+help: wrap the field type in `ManuallyDrop<...>`
+   |
+LL |         e: std::mem::ManuallyDrop<E>,
+   |            +++++++++++++++++++++++ +
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0517, E0740.
+For more information about an error, try `rustc --explain E0517`.