]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/transform/deaggregator.rs
Rollup merge of #57278 - mati865:config_clippy, r=alexcrichton
[rust.git] / src / librustc_mir / transform / deaggregator.rs
1 use rustc::ty::TyCtxt;
2 use rustc::mir::*;
3 use rustc_data_structures::indexed_vec::Idx;
4 use transform::{MirPass, MirSource};
5
6 pub struct Deaggregator;
7
8 impl MirPass for Deaggregator {
9     fn run_pass<'a, 'tcx>(&self,
10                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
11                           _source: MirSource,
12                           mir: &mut Mir<'tcx>) {
13         let (basic_blocks, local_decls) = mir.basic_blocks_and_local_decls_mut();
14         let local_decls = &*local_decls;
15         for bb in basic_blocks {
16             bb.expand_statements(|stmt| {
17                 // FIXME(eddyb) don't match twice on `stmt.kind` (post-NLL).
18                 if let StatementKind::Assign(_, ref rhs) = stmt.kind {
19                     if let Rvalue::Aggregate(ref kind, _) = **rhs {
20                         // FIXME(#48193) Deaggregate arrays when it's cheaper to do so.
21                         if let AggregateKind::Array(_) = **kind {
22                             return None;
23                         }
24                     } else {
25                         return None;
26                     }
27                 } else {
28                     return None;
29                 }
30
31                 let stmt = stmt.replace_nop();
32                 let source_info = stmt.source_info;
33                 let (mut lhs, kind, operands) = match stmt.kind {
34                     StatementKind::Assign(lhs, box rvalue) => {
35                         match rvalue {
36                             Rvalue::Aggregate(kind, operands) => (lhs, kind, operands),
37                             _ => bug!()
38                         }
39                     }
40                     _ => bug!()
41                 };
42
43                 let mut set_discriminant = None;
44                 let active_field_index = match *kind {
45                     AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => {
46                         if adt_def.is_enum() {
47                             set_discriminant = Some(Statement {
48                                 kind: StatementKind::SetDiscriminant {
49                                     place: lhs.clone(),
50                                     variant_index,
51                                 },
52                                 source_info,
53                             });
54                             lhs = lhs.downcast(adt_def, variant_index);
55                         }
56                         active_field_index
57                     }
58                     _ => None
59                 };
60
61                 Some(operands.into_iter().enumerate().map(move |(i, op)| {
62                     let lhs_field = if let AggregateKind::Array(_) = *kind {
63                         // FIXME(eddyb) `offset` should be u64.
64                         let offset = i as u32;
65                         assert_eq!(offset as usize, i);
66                         lhs.clone().elem(ProjectionElem::ConstantIndex {
67                             offset,
68                             // FIXME(eddyb) `min_length` doesn't appear to be used.
69                             min_length: offset + 1,
70                             from_end: false
71                         })
72                     } else {
73                         let ty = op.ty(local_decls, tcx);
74                         let field = Field::new(active_field_index.unwrap_or(i));
75                         lhs.clone().field(field, ty)
76                     };
77                     Statement {
78                         source_info,
79                         kind: StatementKind::Assign(lhs_field, box Rvalue::Use(op)),
80                     }
81                 }).chain(set_discriminant))
82             });
83         }
84     }
85 }