]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/util/aggregate.rs
Rollup merge of #64895 - davidtwco:issue-64130-async-error-definition, r=nikomatsakis
[rust.git] / src / librustc_mir / util / aggregate.rs
1 use rustc::mir::*;
2 use rustc::ty::Ty;
3 use rustc::ty::layout::VariantIdx;
4 use rustc_index::vec::Idx;
5
6 use std::iter::TrustedLen;
7
8 /// Expand `lhs = Rvalue::Aggregate(kind, operands)` into assignments to the fields.
9 ///
10 /// Produces something like
11 ///
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>(
16     mut lhs: Place<'tcx>,
17     operands: impl Iterator<Item=(Operand<'tcx>, Ty<'tcx>)> + TrustedLen,
18     kind: AggregateKind<'tcx>,
19     source_info: SourceInfo,
20 ) -> impl Iterator<Item=Statement<'tcx>> + TrustedLen {
21     let mut set_discriminant = None;
22     let active_field_index = match kind {
23         AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => {
24             if adt_def.is_enum() {
25                 set_discriminant = Some(Statement {
26                     kind: StatementKind::SetDiscriminant {
27                         place: box(lhs.clone()),
28                         variant_index,
29                     },
30                     source_info,
31                 });
32                 lhs = lhs.downcast(adt_def, variant_index);
33             }
34             active_field_index
35         }
36         AggregateKind::Generator(..) => {
37             // Right now we only support initializing generators to
38             // variant 0 (Unresumed).
39             let variant_index = VariantIdx::new(0);
40             set_discriminant = Some(Statement {
41                 kind: StatementKind::SetDiscriminant {
42                     place: box(lhs.clone()),
43                     variant_index,
44                 },
45                 source_info,
46             });
47
48             // Operands are upvars stored on the base place, so no
49             // downcast is necessary.
50
51             None
52         }
53         _ => None
54     };
55
56     operands.into_iter().enumerate().map(move |(i, (op, ty))| {
57         let lhs_field = if let AggregateKind::Array(_) = kind {
58             // FIXME(eddyb) `offset` should be u64.
59             let offset = i as u32;
60             assert_eq!(offset as usize, i);
61             lhs.clone().elem(ProjectionElem::ConstantIndex {
62                 offset,
63                 // FIXME(eddyb) `min_length` doesn't appear to be used.
64                 min_length: offset + 1,
65                 from_end: false
66             })
67         } else {
68             let field = Field::new(active_field_index.unwrap_or(i));
69             lhs.clone().field(field, ty)
70         };
71         Statement {
72             source_info,
73             kind: StatementKind::Assign(box(lhs_field, Rvalue::Use(op))),
74         }
75     }).chain(set_discriminant)
76 }