2 use rustc::ty::layout::VariantIdx;
3 use rustc::ty::{Ty, TyCtxt};
4 use rustc_index::vec::Idx;
6 use std::iter::TrustedLen;
8 /// Expand `lhs = Rvalue::Aggregate(kind, operands)` into assignments to the fields.
10 /// Produces something like
12 /// (lhs as Variant).field0 = arg0; // We only have a downcast if this is an enum
13 /// (lhs as Variant).field1 = arg1;
14 /// discriminant(lhs) = variant_index; // If lhs is an enum or generator.
15 pub fn expand_aggregate<'tcx>(
17 operands: impl Iterator<Item = (Operand<'tcx>, Ty<'tcx>)> + TrustedLen,
18 kind: AggregateKind<'tcx>,
19 source_info: SourceInfo,
21 ) -> impl Iterator<Item = Statement<'tcx>> + TrustedLen {
22 let mut set_discriminant = None;
23 let active_field_index = match kind {
24 AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => {
25 if adt_def.is_enum() {
26 set_discriminant = Some(Statement {
27 kind: StatementKind::SetDiscriminant {
28 place: box (lhs.clone()),
33 lhs = tcx.mk_place_downcast(lhs, adt_def, variant_index);
37 AggregateKind::Generator(..) => {
38 // Right now we only support initializing generators to
39 // variant 0 (Unresumed).
40 let variant_index = VariantIdx::new(0);
41 set_discriminant = Some(Statement {
42 kind: StatementKind::SetDiscriminant { place: box (lhs.clone()), variant_index },
46 // Operands are upvars stored on the base place, so no
47 // downcast is necessary.
57 .map(move |(i, (op, ty))| {
58 let lhs_field = if let AggregateKind::Array(_) = kind {
59 // FIXME(eddyb) `offset` should be u64.
60 let offset = i as u32;
61 assert_eq!(offset as usize, i);
64 ProjectionElem::ConstantIndex {
66 // FIXME(eddyb) `min_length` doesn't appear to be used.
67 min_length: offset + 1,
72 let field = Field::new(active_field_index.unwrap_or(i));
73 tcx.mk_place_field(lhs.clone(), field, ty)
75 Statement { source_info, kind: StatementKind::Assign(box (lhs_field, Rvalue::Use(op))) }
77 .chain(set_discriminant)