about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_abi/src/layout.rs4
-rw-r--r--compiler/rustc_abi/src/lib.rs1
-rw-r--r--tests/ui/generator/issue-113279.rs27
-rw-r--r--tests/ui/generator/issue-113279.stderr16
4 files changed, 46 insertions, 2 deletions
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index aea88641f82..489a8403c3b 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -763,7 +763,9 @@ pub trait LayoutCalculator {
         let mut size = Size::ZERO;
         let only_variant = &variants[FIRST_VARIANT];
         for field in only_variant {
-            assert!(field.0.is_sized());
+            if field.0.is_unsized() {
+                self.delay_bug("unsized field in union".to_string());
+            }
 
             align = align.max(field.align());
             max_repr_align = max_repr_align.max(field.max_repr_align());
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index ef0c763ac20..93b29d037d6 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -1345,7 +1345,6 @@ impl Abi {
 
     /// Discard validity range information and allow undef.
     pub fn to_union(&self) -> Self {
-        assert!(self.is_sized());
         match *self {
             Abi::Scalar(s) => Abi::Scalar(s.to_union()),
             Abi::ScalarPair(s1, s2) => Abi::ScalarPair(s1.to_union(), s2.to_union()),
diff --git a/tests/ui/generator/issue-113279.rs b/tests/ui/generator/issue-113279.rs
new file mode 100644
index 00000000000..f69f804b716
--- /dev/null
+++ b/tests/ui/generator/issue-113279.rs
@@ -0,0 +1,27 @@
+#![feature(generators)]
+
+// `foo` attempts to dereference `""`, which results in an error being reported. Later, the
+// generator transform for `foo` then produces a union which contains a `str` type - unions should
+// not contain unsized types, but this is okay because an error has been reported already.
+// When const propagation happens later in compilation, it attempts to compute the layout of the
+// generator (as part of checking whether something can be const propagated) and in turn attempts
+// to compute the layout of `str` in the context of a union - where this caused an ICE. This test
+// makes sure that doesn't happen again.
+
+fn foo() {
+    let _y = static || {
+        let x = &mut 0;
+        *{
+            yield;
+            x
+        } += match { *"" }.len() {
+            //~^ ERROR cannot move a value of type `str` [E0161]
+            //~^^ ERROR cannot move out of a shared reference [E0507]
+            _ => 0,
+        };
+    };
+}
+
+fn main() {
+    foo()
+}
diff --git a/tests/ui/generator/issue-113279.stderr b/tests/ui/generator/issue-113279.stderr
new file mode 100644
index 00000000000..cc9b64ef9ac
--- /dev/null
+++ b/tests/ui/generator/issue-113279.stderr
@@ -0,0 +1,16 @@
+error[E0161]: cannot move a value of type `str`
+  --> $DIR/issue-113279.rs:17:20
+   |
+LL |         } += match { *"" }.len() {
+   |                    ^^^^^^^ the size of `str` cannot be statically determined
+
+error[E0507]: cannot move out of a shared reference
+  --> $DIR/issue-113279.rs:17:22
+   |
+LL |         } += match { *"" }.len() {
+   |                      ^^^ move occurs because value has type `str`, which does not implement the `Copy` trait
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0161, E0507.
+For more information about an error, try `rustc --explain E0161`.