Skip to content

Commit 0cb1938

Browse files
committed
Fix buggy field access translation
1 parent bea0b15 commit 0cb1938

File tree

10 files changed

+30
-24
lines changed

10 files changed

+30
-24
lines changed

src/librustc/mir/repr.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -962,7 +962,10 @@ pub enum CastKind {
962962
pub enum AggregateKind<'tcx> {
963963
Vec,
964964
Tuple,
965-
Adt(AdtDef<'tcx>, usize, &'tcx Substs<'tcx>),
965+
/// The second field is variant number (discriminant), it's equal to 0
966+
/// for struct and union expressions. The fourth field is active field
967+
/// number and is present only for union expressions.
968+
Adt(AdtDef<'tcx>, usize, &'tcx Substs<'tcx>, Option<usize>),
966969
Closure(DefId, ClosureSubsts<'tcx>),
967970
}
968971

@@ -1069,7 +1072,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
10691072
}
10701073
}
10711074

1072-
Adt(adt_def, variant, substs) => {
1075+
Adt(adt_def, variant, substs, _) => {
10731076
let variant_def = &adt_def.variants[variant];
10741077

10751078
ppaux::parameterized(fmt, substs, variant_def.did,

src/librustc/mir/tcx.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ impl<'tcx> Rvalue<'tcx> {
187187
ops.iter().map(|op| op.ty(mir, tcx)).collect()
188188
))
189189
}
190-
AggregateKind::Adt(def, _, substs) => {
190+
AggregateKind::Adt(def, _, substs, _) => {
191191
Some(tcx.lookup_item_type(def.did).ty.subst(tcx, substs))
192192
}
193193
AggregateKind::Closure(did, substs) => {

src/librustc/mir/visit.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,8 @@ macro_rules! make_mir_visitor {
536536
}
537537
AggregateKind::Adt(_adt_def,
538538
_variant_index,
539-
ref $($mutability)* substs) => {
539+
ref $($mutability)* substs,
540+
_active_field_index) => {
540541
self.visit_substs(substs);
541542
}
542543
AggregateKind::Closure(ref $($mutability)* def_id,

src/librustc_mir/build/expr/as_rvalue.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
181181
ExprKind::Adt {
182182
adt_def, variant_index, substs, fields, base
183183
} => { // see (*) above
184+
let is_union = adt_def.adt_kind() == ty::AdtKind::Union;
185+
let active_field_index = if is_union { Some(fields[0].name.index()) } else { None };
186+
184187
// first process the set of fields that were provided
185188
// (evaluating them in order given by user)
186189
let fields_map: FnvHashMap<_, _> =
@@ -204,11 +207,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
204207
})
205208
.collect()
206209
} else {
207-
field_names.iter().map(|n| fields_map[n].clone()).collect()
210+
field_names.iter().filter_map(|n| fields_map.get(n).cloned()).collect()
208211
};
209212

210-
block.and(Rvalue::Aggregate(AggregateKind::Adt(adt_def, variant_index, substs),
211-
fields))
213+
let adt = AggregateKind::Adt(adt_def, variant_index, substs, active_field_index);
214+
block.and(Rvalue::Aggregate(adt, fields))
212215
}
213216
ExprKind::Assign { .. } |
214217
ExprKind::AssignOp { .. } => {

src/librustc_mir/transform/deaggregator.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ impl<'tcx> MirPass<'tcx> for Deaggregator {
5757
_ => span_bug!(src_info.span, "expected aggregate, not {:?}", rhs),
5858
};
5959
let (adt_def, variant, substs) = match agg_kind {
60-
&AggregateKind::Adt(adt_def, variant, substs) => (adt_def, variant, substs),
60+
&AggregateKind::Adt(adt_def, variant, substs, None) => (adt_def, variant, substs),
6161
_ => span_bug!(src_info.span, "expected struct, not {:?}", rhs),
6262
};
6363
let n = bb.statements.len();
@@ -120,7 +120,7 @@ fn get_aggregate_statement_index<'a, 'tcx, 'b>(start: usize,
120120
_ => continue,
121121
};
122122
let (adt_def, variant) = match kind {
123-
&AggregateKind::Adt(adt_def, variant, _) => (adt_def, variant),
123+
&AggregateKind::Adt(adt_def, variant, _, None) => (adt_def, variant),
124124
_ => continue,
125125
};
126126
if operands.len() == 0 {

src/librustc_mir/transform/qualify_consts.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
705705
}
706706

707707
Rvalue::Aggregate(ref kind, _) => {
708-
if let AggregateKind::Adt(def, _, _) = *kind {
708+
if let AggregateKind::Adt(def, _, _, _) = *kind {
709709
if def.has_dtor() {
710710
self.add(Qualif::NEEDS_DROP);
711711
self.deny_drop();

src/librustc_trans/mir/constant.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
547547
self.monomorphize(&substs));
548548
}
549549

550-
let val = if let mir::AggregateKind::Adt(adt_def, index, _) = *kind {
550+
let val = if let mir::AggregateKind::Adt(adt_def, index, _, _) = *kind {
551551
let repr = adt::represent_type(self.ccx, dest_ty);
552552
let disr = Disr::from(adt_def.variants[index].disr_val);
553553
adt::trans_const(self.ccx, &repr, disr, &fields)

src/librustc_trans/mir/rvalue.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
110110

111111
mir::Rvalue::Aggregate(ref kind, ref operands) => {
112112
match *kind {
113-
mir::AggregateKind::Adt(adt_def, index, _) => {
113+
mir::AggregateKind::Adt(adt_def, variant_index, _, active_field_index) => {
114114
let repr = adt::represent_type(bcx.ccx(), dest.ty.to_ty(bcx.tcx()));
115-
let disr = Disr::from(adt_def.variants[index].disr_val);
115+
let disr = Disr::from(adt_def.variants[variant_index].disr_val);
116116
bcx.with_block(|bcx| {
117117
adt::trans_set_discr(bcx, &repr, dest.llval, Disr::from(disr));
118118
});
@@ -121,8 +121,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
121121
// Do not generate stores and GEPis for zero-sized fields.
122122
if !common::type_is_zero_size(bcx.ccx(), op.ty) {
123123
let val = adt::MaybeSizedValue::sized(dest.llval);
124-
let lldest_i = adt::trans_field_ptr_builder(&bcx, &repr,
125-
val, disr, i);
124+
let field_index = active_field_index.unwrap_or(i);
125+
let lldest_i = adt::trans_field_ptr_builder(&bcx, &repr, val,
126+
disr, field_index);
126127
self.store_operand(&bcx, lldest_i, op);
127128
}
128129
}

src/test/run-pass/union-basic.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,12 @@ fn main() {
4848
assert_eq!(a, 10);
4949
}
5050

51-
let mut w: W = unsafe { zeroed() };
51+
let mut w = W { b: 0 };
5252
unsafe {
5353
assert_eq!(w.a, 0);
5454
assert_eq!(w.b, 0);
5555
// w.a = 1;
56-
// assert_eq!(w.a, 0);
57-
// assert_eq!(w.b, 0);
56+
assert_eq!(w.a, 0);
57+
assert_eq!(w.b, 0);
5858
}
5959
}

src/test/run-pass/union-pat-refutability.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,9 @@ fn refut(w: W) {
5454
}
5555

5656
fn main() {
57-
// ICE
58-
// let v = Value { tag: Tag::I, u: U { i: 1 } };
59-
// assert_eq!(is_zero(v), false);
57+
let v = Value { tag: Tag::I, u: U { i: 1 } };
58+
assert_eq!(is_zero(v), false);
6059

61-
// ICE
62-
// let w = W { a: 11 };
63-
// refut(w);
60+
let w = W { a: 11 };
61+
refut(w);
6462
}

0 commit comments

Comments
 (0)