]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/transform/erase_regions.rs
Auto merge of #31445 - saurvs:master, r=brson
[rust.git] / src / librustc_mir / transform / erase_regions.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! This pass erases all early-bound regions from the types occuring in the MIR.
12 //! We want to do this once just before trans, so trans does not have to take
13 //! care erasing regions all over the place.
14
15 use rustc::middle::ty;
16 use rustc::mir::repr::*;
17 use transform::MirPass;
18 use mir_map::MirMap;
19
20 pub fn erase_regions<'tcx>(tcx: &ty::ctxt<'tcx>, mir_map: &mut MirMap<'tcx>) {
21     let mut eraser = EraseRegions::new(tcx);
22
23     for mir in mir_map.iter_mut().map(|(_, v)| v) {
24         eraser.run_on_mir(mir);
25     }
26 }
27
28 pub struct EraseRegions<'a, 'tcx: 'a> {
29     tcx: &'a ty::ctxt<'tcx>,
30 }
31
32 impl<'a, 'tcx> MirPass<'tcx> for EraseRegions<'a, 'tcx> {
33
34     fn run_on_mir(&mut self, mir: &mut Mir<'tcx>) {
35
36         for basic_block in &mut mir.basic_blocks {
37             self.erase_regions_basic_block(basic_block);
38         }
39
40         self.erase_regions_return_ty(&mut mir.return_ty);
41
42         self.erase_regions_tys(mir.var_decls.iter_mut().map(|d| &mut d.ty));
43         self.erase_regions_tys(mir.arg_decls.iter_mut().map(|d| &mut d.ty));
44         self.erase_regions_tys(mir.temp_decls.iter_mut().map(|d| &mut d.ty));
45     }
46 }
47
48 impl<'a, 'tcx> EraseRegions<'a, 'tcx> {
49
50     pub fn new(tcx: &'a ty::ctxt<'tcx>) -> EraseRegions<'a, 'tcx> {
51         EraseRegions {
52             tcx: tcx
53         }
54     }
55
56     fn erase_regions_basic_block(&mut self,
57                                  basic_block: &mut BasicBlockData<'tcx>) {
58         for statement in &mut basic_block.statements {
59             self.erase_regions_statement(statement);
60         }
61
62         self.erase_regions_terminator(basic_block.terminator_mut());
63     }
64
65     fn erase_regions_statement(&mut self,
66                                statement: &mut Statement<'tcx>) {
67         match statement.kind {
68             StatementKind::Assign(ref mut lvalue, ref mut rvalue) => {
69                 self.erase_regions_lvalue(lvalue);
70                 self.erase_regions_rvalue(rvalue);
71             }
72         }
73     }
74
75     fn erase_regions_terminator(&mut self,
76                                 terminator: &mut Terminator<'tcx>) {
77         match *terminator {
78             Terminator::Goto { .. } |
79             Terminator::Resume |
80             Terminator::Return => {
81                 /* nothing to do */
82             }
83             Terminator::If { ref mut cond, .. } => {
84                 self.erase_regions_operand(cond);
85             }
86             Terminator::Switch { ref mut discr, .. } => {
87                 self.erase_regions_lvalue(discr);
88             }
89             Terminator::SwitchInt { ref mut discr, ref mut switch_ty, .. } => {
90                 self.erase_regions_lvalue(discr);
91                 *switch_ty = self.tcx.erase_regions(switch_ty);
92             },
93             Terminator::Drop { ref mut value, .. } => {
94                 self.erase_regions_lvalue(value);
95             }
96             Terminator::Call { ref mut func, ref mut args, ref mut destination, .. } => {
97                 if let Some((ref mut destination, _)) = *destination {
98                     self.erase_regions_lvalue(destination);
99                 }
100                 self.erase_regions_operand(func);
101                 for arg in &mut *args {
102                     self.erase_regions_operand(arg);
103                 }
104             }
105         }
106     }
107
108     fn erase_regions_operand(&mut self, operand: &mut Operand<'tcx>) {
109         match *operand {
110             Operand::Consume(ref mut lvalue) => {
111                 self.erase_regions_lvalue(lvalue);
112             }
113             Operand::Constant(ref mut constant) => {
114                 self.erase_regions_constant(constant);
115             }
116         }
117     }
118
119     fn erase_regions_lvalue(&mut self, lvalue: &mut Lvalue<'tcx>) {
120         match *lvalue {
121             Lvalue::Var(_)        |
122             Lvalue::Temp(_)       |
123             Lvalue::Arg(_)        |
124             Lvalue::Static(_)     |
125             Lvalue::ReturnPointer => {}
126             Lvalue::Projection(ref mut lvalue_projection) => {
127                 self.erase_regions_lvalue(&mut lvalue_projection.base);
128                 match lvalue_projection.elem {
129                     ProjectionElem::Deref              |
130                     ProjectionElem::Field(_)           |
131                     ProjectionElem::Downcast(..)       |
132                     ProjectionElem::ConstantIndex {..} => { /* nothing to do */ }
133                     ProjectionElem::Index(ref mut index) => {
134                         self.erase_regions_operand(index);
135                     }
136                 }
137             }
138         }
139     }
140
141     fn erase_regions_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>) {
142         match *rvalue {
143             Rvalue::Use(ref mut operand) => {
144                 self.erase_regions_operand(operand)
145             }
146             Rvalue::Repeat(ref mut operand, ref mut value) => {
147                 self.erase_regions_operand(operand);
148                 value.ty = self.tcx.erase_regions(&value.ty);
149             }
150             Rvalue::Ref(ref mut region, _, ref mut lvalue) => {
151                 *region = ty::ReStatic;
152                 self.erase_regions_lvalue(lvalue);
153             }
154             Rvalue::Len(ref mut lvalue) => self.erase_regions_lvalue(lvalue),
155             Rvalue::Cast(_, ref mut operand, ref mut ty) => {
156                 self.erase_regions_operand(operand);
157                 *ty = self.tcx.erase_regions(ty);
158             }
159             Rvalue::BinaryOp(_, ref mut operand1, ref mut operand2) => {
160                 self.erase_regions_operand(operand1);
161                 self.erase_regions_operand(operand2);
162             }
163             Rvalue::UnaryOp(_, ref mut operand) => {
164                 self.erase_regions_operand(operand);
165             }
166             Rvalue::Box(ref mut ty) => *ty = self.tcx.erase_regions(ty),
167             Rvalue::Aggregate(ref mut aggregate_kind, ref mut operands) => {
168                 match *aggregate_kind {
169                     AggregateKind::Vec   |
170                     AggregateKind::Tuple => {},
171                     AggregateKind::Adt(_, _, ref mut substs) => {
172                         let erased = self.tcx.erase_regions(*substs);
173                         *substs = self.tcx.mk_substs(erased);
174                     }
175                     AggregateKind::Closure(def_id, ref mut closure_substs) => {
176                         let cloned = Box::new(closure_substs.clone());
177                         let ty = self.tcx.mk_closure_from_closure_substs(def_id,
178                                                                          cloned);
179                         let erased = self.tcx.erase_regions(&ty);
180                         *closure_substs = match erased.sty {
181                             ty::TyClosure(_, ref closure_substs) => &*closure_substs,
182                             _ => unreachable!()
183                         };
184                     }
185                 }
186                 for operand in &mut *operands {
187                     self.erase_regions_operand(operand);
188                 }
189             }
190             Rvalue::Slice { ref mut input, .. } => {
191                 self.erase_regions_lvalue(input);
192             }
193             Rvalue::InlineAsm(_) => {},
194         }
195     }
196
197     fn erase_regions_constant(&mut self, constant: &mut Constant<'tcx>) {
198         constant.ty = self.tcx.erase_regions(&constant.ty);
199         match constant.literal {
200             Literal::Item { ref mut substs, .. } => {
201                 *substs = self.tcx.mk_substs(self.tcx.erase_regions(substs));
202             }
203             Literal::Value { .. } => { /* nothing to do */ }
204         }
205     }
206
207     fn erase_regions_return_ty(&mut self, fn_output: &mut ty::FnOutput<'tcx>) {
208         match *fn_output {
209             ty::FnConverging(ref mut ty) => {
210                 *ty = self.tcx.erase_regions(ty);
211             },
212             ty::FnDiverging => {}
213         }
214     }
215
216     fn erase_regions_tys<'b, T>(&mut self, tys: T)
217         where T: Iterator<Item = &'b mut ty::Ty<'tcx>>,
218               'tcx: 'b
219     {
220         for ty in tys {
221             *ty = self.tcx.erase_regions(ty);
222         }
223     }
224 }