diff options
| -rw-r--r-- | src/librustc/mir/repr.rs | 7 | ||||
| -rw-r--r-- | src/librustc/mir/tcx.rs | 2 | ||||
| -rw-r--r-- | src/librustc/mir/visit.rs | 3 | ||||
| -rw-r--r-- | src/librustc_mir/build/expr/as_rvalue.rs | 9 | ||||
| -rw-r--r-- | src/librustc_mir/transform/deaggregator.rs | 4 | ||||
| -rw-r--r-- | src/librustc_mir/transform/qualify_consts.rs | 2 | ||||
| -rw-r--r-- | src/librustc_trans/mir/constant.rs | 2 | ||||
| -rw-r--r-- | src/librustc_trans/mir/rvalue.rs | 9 | ||||
| -rw-r--r-- | src/test/run-pass/union-basic.rs | 6 | ||||
| -rw-r--r-- | src/test/run-pass/union-pat-refutability.rs | 10 |
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); } |
