]> git.proxmox.com Git - rustc.git/blame - src/librustc_mir/util/aggregate.rs
New upstream version 1.47.0+dfsg1
[rustc.git] / src / librustc_mir / util / aggregate.rs
CommitLineData
e74abb32 1use rustc_index::vec::Idx;
ba9703b0
XL
2use rustc_middle::mir::*;
3use rustc_middle::ty::{Ty, TyCtxt};
4use rustc_target::abi::VariantIdx;
dc9dc135
XL
5
6use 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.
15pub 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}