about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/mir/repr.rs7
-rw-r--r--src/librustc/mir/tcx.rs2
-rw-r--r--src/librustc/mir/visit.rs3
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs9
-rw-r--r--src/librustc_mir/transform/deaggregator.rs4
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs2
-rw-r--r--src/librustc_trans/mir/constant.rs2
-rw-r--r--src/librustc_trans/mir/rvalue.rs9
-rw-r--r--src/test/run-pass/union-basic.rs6
-rw-r--r--src/test/run-pass/union-pat-refutability.rs10
10 files changed, 30 insertions, 24 deletions
diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs
index 8145c0aae3f..a2abaa5e12f 100644
--- a/src/librustc/mir/repr.rs
+++ b/src/librustc/mir/repr.rs
@@ -962,7 +962,10 @@ pub enum CastKind {
 pub enum AggregateKind<'tcx> {
     Vec,
     Tuple,
-    Adt(AdtDef<'tcx>, usize, &'tcx Substs<'tcx>),
+    /// The second field is variant number (discriminant), it's equal to 0
+    /// for struct and union expressions. The fourth field is active field
+    /// number and is present only for union expressions.
+    Adt(AdtDef<'tcx>, usize, &'tcx Substs<'tcx>, Option<usize>),
     Closure(DefId, ClosureSubsts<'tcx>),
 }
 
@@ -1069,7 +1072,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
                         }
                     }
 
-                    Adt(adt_def, variant, substs) => {
+                    Adt(adt_def, variant, substs, _) => {
                         let variant_def = &adt_def.variants[variant];
 
                         ppaux::parameterized(fmt, substs, variant_def.did,
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index 76e5f8598c1..a0ccc72aa1f 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -187,7 +187,7 @@ impl<'tcx> Rvalue<'tcx> {
                             ops.iter().map(|op| op.ty(mir, tcx)).collect()
                         ))
                     }
-                    AggregateKind::Adt(def, _, substs) => {
+                    AggregateKind::Adt(def, _, substs, _) => {
                         Some(tcx.lookup_item_type(def.did).ty.subst(tcx, substs))
                     }
                     AggregateKind::Closure(did, substs) => {
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 2771880735c..c2d0b2c686e 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -536,7 +536,8 @@ macro_rules! make_mir_visitor {
                             }
                             AggregateKind::Adt(_adt_def,
                                                _variant_index,
-                                               ref $($mutability)* substs) => {
+                                               ref $($mutability)* substs,
+                                               _active_field_index) => {
                                 self.visit_substs(substs);
                             }
                             AggregateKind::Closure(ref $($mutability)* def_id,
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index dafc53d3c15..6ea1fb50360 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -181,6 +181,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             ExprKind::Adt {
                 adt_def, variant_index, substs, fields, base
             } => { // see (*) above
+                let is_union = adt_def.adt_kind() == ty::AdtKind::Union;
+                let active_field_index = if is_union { Some(fields[0].name.index()) } else { None };
+
                 // first process the set of fields that were provided
                 // (evaluating them in order given by user)
                 let fields_map: FnvHashMap<_, _> =
@@ -204,11 +207,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                         })
                         .collect()
                 } else {
-                    field_names.iter().map(|n| fields_map[n].clone()).collect()
+                    field_names.iter().filter_map(|n| fields_map.get(n).cloned()).collect()
                 };
 
-                block.and(Rvalue::Aggregate(AggregateKind::Adt(adt_def, variant_index, substs),
-                                            fields))
+                let adt = AggregateKind::Adt(adt_def, variant_index, substs, active_field_index);
+                block.and(Rvalue::Aggregate(adt, fields))
             }
             ExprKind::Assign { .. } |
             ExprKind::AssignOp { .. } => {
diff --git a/src/librustc_mir/transform/deaggregator.rs b/src/librustc_mir/transform/deaggregator.rs
index cb3010a5cf4..77af02c18c6 100644
--- a/src/librustc_mir/transform/deaggregator.rs
+++ b/src/librustc_mir/transform/deaggregator.rs
@@ -57,7 +57,7 @@ impl<'tcx> MirPass<'tcx> for Deaggregator {
                 _ => span_bug!(src_info.span, "expected aggregate, not {:?}", rhs),
             };
             let (adt_def, variant, substs) = match agg_kind {
-                &AggregateKind::Adt(adt_def, variant, substs) => (adt_def, variant, substs),
+                &AggregateKind::Adt(adt_def, variant, substs, None) => (adt_def, variant, substs),
                 _ => span_bug!(src_info.span, "expected struct, not {:?}", rhs),
             };
             let n = bb.statements.len();
@@ -120,7 +120,7 @@ fn get_aggregate_statement_index<'a, 'tcx, 'b>(start: usize,
             _ => continue,
         };
         let (adt_def, variant) = match kind {
-            &AggregateKind::Adt(adt_def, variant, _) => (adt_def, variant),
+            &AggregateKind::Adt(adt_def, variant, _, None) => (adt_def, variant),
             _ => continue,
         };
         if operands.len() == 0 {
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 2fc90ab27a0..6c6a5f7fc74 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -705,7 +705,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
             }
 
             Rvalue::Aggregate(ref kind, _) => {
-                if let AggregateKind::Adt(def, _, _) = *kind {
+                if let AggregateKind::Adt(def, _, _, _) = *kind {
                     if def.has_dtor() {
                         self.add(Qualif::NEEDS_DROP);
                         self.deny_drop();
diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs
index ade266a580e..15dc7bb4421 100644
--- a/src/librustc_trans/mir/constant.rs
+++ b/src/librustc_trans/mir/constant.rs
@@ -547,7 +547,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
                                                         self.monomorphize(&substs));
                 }
 
-                let val = if let mir::AggregateKind::Adt(adt_def, index, _) = *kind {
+                let val = if let mir::AggregateKind::Adt(adt_def, index, _, _) = *kind {
                     let repr = adt::represent_type(self.ccx, dest_ty);
                     let disr = Disr::from(adt_def.variants[index].disr_val);
                     adt::trans_const(self.ccx, &repr, disr, &fields)
diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs
index 13484cb7a4e..21b019d7e24 100644
--- a/src/librustc_trans/mir/rvalue.rs
+++ b/src/librustc_trans/mir/rvalue.rs
@@ -110,9 +110,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
 
             mir::Rvalue::Aggregate(ref kind, ref operands) => {
                 match *kind {
-                    mir::AggregateKind::Adt(adt_def, index, _) => {
+                    mir::AggregateKind::Adt(adt_def, variant_index, _, active_field_index) => {
                         let repr = adt::represent_type(bcx.ccx(), dest.ty.to_ty(bcx.tcx()));
-                        let disr = Disr::from(adt_def.variants[index].disr_val);
+                        let disr = Disr::from(adt_def.variants[variant_index].disr_val);
                         bcx.with_block(|bcx| {
                             adt::trans_set_discr(bcx, &repr, dest.llval, Disr::from(disr));
                         });
@@ -121,8 +121,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                             // Do not generate stores and GEPis for zero-sized fields.
                             if !common::type_is_zero_size(bcx.ccx(), op.ty) {
                                 let val = adt::MaybeSizedValue::sized(dest.llval);
-                                let lldest_i = adt::trans_field_ptr_builder(&bcx, &repr,
-                                                                            val, disr, i);
+                                let field_index = active_field_index.unwrap_or(i);
+                                let lldest_i = adt::trans_field_ptr_builder(&bcx, &repr, val,
+                                                                            disr, field_index);
                                 self.store_operand(&bcx, lldest_i, op);
                             }
                         }
diff --git a/src/test/run-pass/union-basic.rs b/src/test/run-pass/union-basic.rs
index afbfe5bf92b..a00bd73115a 100644
--- a/src/test/run-pass/union-basic.rs
+++ b/src/test/run-pass/union-basic.rs
@@ -48,12 +48,12 @@ fn main() {
         assert_eq!(a, 10);
     }
 
-    let mut w: W = unsafe { zeroed() };
+    let mut w = W { b: 0 };
     unsafe {
         assert_eq!(w.a, 0);
         assert_eq!(w.b, 0);
         // w.a = 1;
-        // assert_eq!(w.a, 0);
-        // assert_eq!(w.b, 0);
+        assert_eq!(w.a, 0);
+        assert_eq!(w.b, 0);
     }
 }
diff --git a/src/test/run-pass/union-pat-refutability.rs b/src/test/run-pass/union-pat-refutability.rs
index a57c1103a9b..e6144f35f1d 100644
--- a/src/test/run-pass/union-pat-refutability.rs
+++ b/src/test/run-pass/union-pat-refutability.rs
@@ -54,11 +54,9 @@ fn refut(w: W) {
 }
 
 fn main() {
-    // ICE
-    // let v = Value { tag: Tag::I, u: U { i: 1 } };
-    // assert_eq!(is_zero(v), false);
+    let v = Value { tag: Tag::I, u: U { i: 1 } };
+    assert_eq!(is_zero(v), false);
 
-    // ICE
-    // let w = W { a: 11 };
-    // refut(w);
+    let w = W { a: 11 };
+    refut(w);
 }