]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/util/aggregate.rs
Rollup merge of #75837 - GuillaumeGomez:fix-font-color-help-button, r=Cldfire
[rust.git] / src / librustc_mir / util / aggregate.rs
1 use rustc_index::vec::Idx;
2 use rustc_middle::mir::*;
3 use rustc_middle::ty::{Ty, TyCtxt};
4 use rustc_target::abi::VariantIdx;
5
6 use std::convert::TryFrom;
7 use std::iter::TrustedLen;
8
9 /// Expand `lhs = Rvalue::Aggregate(kind, operands)` into assignments to the fields.
10 ///
11 /// Produces something like
12 ///
13 /// (lhs as Variant).field0 = arg0;     // We only have a downcast if this is an enum
14 /// (lhs as Variant).field1 = arg1;
15 /// discriminant(lhs) = variant_index;  // If lhs is an enum or generator.
16 pub fn expand_aggregate<'tcx>(
17     mut lhs: Place<'tcx>,
18     operands: impl Iterator<Item = (Operand<'tcx>, Ty<'tcx>)> + TrustedLen,
19     kind: AggregateKind<'tcx>,
20     source_info: SourceInfo,
21     tcx: TyCtxt<'tcx>,
22 ) -> impl Iterator<Item = Statement<'tcx>> + TrustedLen {
23     let mut set_discriminant = None;
24     let active_field_index = match kind {
25         AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => {
26             if adt_def.is_enum() {
27                 set_discriminant = Some(Statement {
28                     kind: StatementKind::SetDiscriminant { place: box (lhs), variant_index },
29                     source_info,
30                 });
31                 lhs = tcx.mk_place_downcast(lhs, adt_def, variant_index);
32             }
33             active_field_index
34         }
35         AggregateKind::Generator(..) => {
36             // Right now we only support initializing generators to
37             // variant 0 (Unresumed).
38             let variant_index = VariantIdx::new(0);
39             set_discriminant = Some(Statement {
40                 kind: StatementKind::SetDiscriminant { place: box (lhs), variant_index },
41                 source_info,
42             });
43
44             // Operands are upvars stored on the base place, so no
45             // downcast is necessary.
46
47             None
48         }
49         _ => None,
50     };
51
52     operands
53         .enumerate()
54         .map(move |(i, (op, ty))| {
55             let lhs_field = if let AggregateKind::Array(_) = kind {
56                 let offset = u64::try_from(i).unwrap();
57                 tcx.mk_place_elem(
58                     lhs,
59                     ProjectionElem::ConstantIndex {
60                         offset,
61                         min_length: offset + 1,
62                         from_end: false,
63                     },
64                 )
65             } else {
66                 let field = Field::new(active_field_index.unwrap_or(i));
67                 tcx.mk_place_field(lhs, field, ty)
68             };
69             Statement { source_info, kind: StatementKind::Assign(box (lhs_field, Rvalue::Use(op))) }
70         })
71         .chain(set_discriminant)
72 }