about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/ty/layout.rs22
-rw-r--r--src/test/run-pass/issue-46845.rs39
2 files changed, 50 insertions, 11 deletions
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 978c6c74233..bf76f6e7d1d 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -1352,17 +1352,6 @@ impl<'a, 'tcx> LayoutDetails {
                     }).collect::<Result<Vec<_>, _>>()
                 }).collect::<Result<Vec<_>, _>>()?;
 
-                let (inh_first, inh_second) = {
-                    let mut inh_variants = (0..variants.len()).filter(|&v| {
-                        variants[v].iter().all(|f| f.abi != Abi::Uninhabited)
-                    });
-                    (inh_variants.next(), inh_variants.next())
-                };
-                if inh_first.is_none() {
-                    // Uninhabited because it has no variants, or only uninhabited ones.
-                    return Ok(tcx.intern_layout(LayoutDetails::uninhabited(0)));
-                }
-
                 if def.is_union() {
                     let packed = def.repr.packed();
                     if packed && def.repr.align > 0 {
@@ -1400,6 +1389,17 @@ impl<'a, 'tcx> LayoutDetails {
                     }));
                 }
 
+                let (inh_first, inh_second) = {
+                    let mut inh_variants = (0..variants.len()).filter(|&v| {
+                        variants[v].iter().all(|f| f.abi != Abi::Uninhabited)
+                    });
+                    (inh_variants.next(), inh_variants.next())
+                };
+                if inh_first.is_none() {
+                    // Uninhabited because it has no variants, or only uninhabited ones.
+                    return Ok(tcx.intern_layout(LayoutDetails::uninhabited(0)));
+                }
+
                 let is_struct = !def.is_enum() ||
                     // Only one variant is inhabited.
                     (inh_second.is_none() &&
diff --git a/src/test/run-pass/issue-46845.rs b/src/test/run-pass/issue-46845.rs
new file mode 100644
index 00000000000..235d3982a9c
--- /dev/null
+++ b/src/test/run-pass/issue-46845.rs
@@ -0,0 +1,39 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// To work around #46855
+// compile-flags: -Z mir-opt-level=0
+// Regression test for the inhabitedness of unions with uninhabited variants, issue #46845
+
+use std::mem;
+
+#[derive(Copy, Clone)]
+enum Never { }
+
+// A single uninhabited variant shouldn't make the whole union uninhabited.
+union Foo {
+    a: u64,
+    _b: Never
+}
+
+// If all the variants are uninhabited, however, the union should be uninhabited.
+union Bar {
+    _a: (Never, u64),
+    _b: (u64, Never)
+}
+
+fn main() {
+    assert_eq!(mem::size_of::<Foo>(), 8);
+    assert_eq!(mem::size_of::<Bar>(), 0);
+
+    let f = [Foo { a: 42 }, Foo { a: 10 }];
+    println!("{}", unsafe { f[0].a });
+    assert_eq!(unsafe { f[1].a }, 10);
+}