1 use rustc_index
::vec
::Idx
;
2 use rustc_middle
::mir
::*;
3 use rustc_middle
::ty
::{Ty, TyCtxt}
;
4 use rustc_target
::abi
::VariantIdx
;
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 { place: box (lhs), variant_index }
,
30 lhs
= tcx
.mk_place_downcast(lhs
, adt_def
, variant_index
);
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
{
39 kind
: StatementKind
::SetDiscriminant { place: box (lhs), variant_index }
,
43 // Operands are upvars stored on the base place, so no
44 // downcast is necessary.
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
);
60 ProjectionElem
::ConstantIndex
{
62 // FIXME(eddyb) `min_length` doesn't appear to be used.
63 min_length
: offset
+ 1,
68 let field
= Field
::new(active_field_index
.unwrap_or(i
));
69 tcx
.mk_place_field(lhs
, field
, ty
)
71 Statement { source_info, kind: StatementKind::Assign(box (lhs_field, Rvalue::Use(op))) }
73 .chain(set_discriminant
)