]>
Commit | Line | Data |
---|---|---|
e74abb32 | 1 | use rustc_index::vec::Idx; |
ba9703b0 XL |
2 | use rustc_middle::mir::*; |
3 | use rustc_middle::ty::{Ty, TyCtxt}; | |
4 | use rustc_target::abi::VariantIdx; | |
dc9dc135 XL |
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>, | |
dfeec247 | 17 | operands: impl Iterator<Item = (Operand<'tcx>, Ty<'tcx>)> + TrustedLen, |
dc9dc135 XL |
18 | kind: AggregateKind<'tcx>, |
19 | source_info: SourceInfo, | |
e74abb32 | 20 | tcx: TyCtxt<'tcx>, |
dfeec247 | 21 | ) -> impl Iterator<Item = Statement<'tcx>> + TrustedLen { |
dc9dc135 XL |
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 { | |
dfeec247 | 27 | kind: StatementKind::SetDiscriminant { place: box (lhs), variant_index }, |
dc9dc135 XL |
28 | source_info, |
29 | }); | |
e74abb32 | 30 | lhs = tcx.mk_place_downcast(lhs, adt_def, variant_index); |
dc9dc135 XL |
31 | } |
32 | active_field_index | |
33 | } | |
34 | AggregateKind::Generator(..) => { | |
35 | // Right now we only support initializing generators to | |
36 | // variant 0 (Unresumed). | |
37 | let variant_index = VariantIdx::new(0); | |
38 | set_discriminant = Some(Statement { | |
dfeec247 | 39 | kind: StatementKind::SetDiscriminant { place: box (lhs), variant_index }, |
dc9dc135 XL |
40 | source_info, |
41 | }); | |
42 | ||
43 | // Operands are upvars stored on the base place, so no | |
44 | // downcast is necessary. | |
45 | ||
46 | None | |
47 | } | |
dfeec247 | 48 | _ => None, |
dc9dc135 XL |
49 | }; |
50 | ||
dfeec247 | 51 | operands |
dfeec247 XL |
52 | .enumerate() |
53 | .map(move |(i, (op, ty))| { | |
54 | let lhs_field = if let AggregateKind::Array(_) = kind { | |
55 | // FIXME(eddyb) `offset` should be u64. | |
56 | let offset = i as u32; | |
57 | assert_eq!(offset as usize, i); | |
58 | tcx.mk_place_elem( | |
ba9703b0 | 59 | lhs, |
dfeec247 XL |
60 | ProjectionElem::ConstantIndex { |
61 | offset, | |
62 | // FIXME(eddyb) `min_length` doesn't appear to be used. | |
63 | min_length: offset + 1, | |
64 | from_end: false, | |
65 | }, | |
66 | ) | |
67 | } else { | |
68 | let field = Field::new(active_field_index.unwrap_or(i)); | |
ba9703b0 | 69 | tcx.mk_place_field(lhs, field, ty) |
dfeec247 XL |
70 | }; |
71 | Statement { source_info, kind: StatementKind::Assign(box (lhs_field, Rvalue::Use(op))) } | |
72 | }) | |
73 | .chain(set_discriminant) | |
dc9dc135 | 74 | } |