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.
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.
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.
15 use rustc::middle::ty;
16 use rustc::mir::repr::*;
17 use transform::MirPass;
20 pub fn erase_regions<'tcx>(tcx: &ty::ctxt<'tcx>, mir_map: &mut MirMap<'tcx>) {
21 let mut eraser = EraseRegions::new(tcx);
23 for mir in mir_map.iter_mut().map(|(_, v)| v) {
24 eraser.run_on_mir(mir);
28 pub struct EraseRegions<'a, 'tcx: 'a> {
29 tcx: &'a ty::ctxt<'tcx>,
32 impl<'a, 'tcx> MirPass<'tcx> for EraseRegions<'a, 'tcx> {
34 fn run_on_mir(&mut self, mir: &mut Mir<'tcx>) {
36 for basic_block in &mut mir.basic_blocks {
37 self.erase_regions_basic_block(basic_block);
40 self.erase_regions_return_ty(&mut mir.return_ty);
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));
48 impl<'a, 'tcx> EraseRegions<'a, 'tcx> {
50 pub fn new(tcx: &'a ty::ctxt<'tcx>) -> EraseRegions<'a, 'tcx> {
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);
62 self.erase_regions_terminator(basic_block.terminator_mut());
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);
75 fn erase_regions_terminator(&mut self,
76 terminator: &mut Terminator<'tcx>) {
78 Terminator::Goto { .. } |
80 Terminator::Return => {
83 Terminator::If { ref mut cond, .. } => {
84 self.erase_regions_operand(cond);
86 Terminator::Switch { ref mut discr, .. } => {
87 self.erase_regions_lvalue(discr);
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);
93 Terminator::Drop { ref mut value, .. } => {
94 self.erase_regions_lvalue(value);
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);
100 self.erase_regions_operand(func);
101 for arg in &mut *args {
102 self.erase_regions_operand(arg);
108 fn erase_regions_operand(&mut self, operand: &mut Operand<'tcx>) {
110 Operand::Consume(ref mut lvalue) => {
111 self.erase_regions_lvalue(lvalue);
113 Operand::Constant(ref mut constant) => {
114 self.erase_regions_constant(constant);
119 fn erase_regions_lvalue(&mut self, lvalue: &mut Lvalue<'tcx>) {
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);
141 fn erase_regions_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>) {
143 Rvalue::Use(ref mut operand) => {
144 self.erase_regions_operand(operand)
146 Rvalue::Repeat(ref mut operand, ref mut value) => {
147 self.erase_regions_operand(operand);
148 value.ty = self.tcx.erase_regions(&value.ty);
150 Rvalue::Ref(ref mut region, _, ref mut lvalue) => {
151 *region = ty::ReStatic;
152 self.erase_regions_lvalue(lvalue);
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);
159 Rvalue::BinaryOp(_, ref mut operand1, ref mut operand2) => {
160 self.erase_regions_operand(operand1);
161 self.erase_regions_operand(operand2);
163 Rvalue::UnaryOp(_, ref mut operand) => {
164 self.erase_regions_operand(operand);
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 {
170 AggregateKind::Tuple => {},
171 AggregateKind::Adt(_, _, ref mut substs) => {
172 let erased = self.tcx.erase_regions(*substs);
173 *substs = self.tcx.mk_substs(erased);
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,
179 let erased = self.tcx.erase_regions(&ty);
180 *closure_substs = match erased.sty {
181 ty::TyClosure(_, ref closure_substs) => &*closure_substs,
186 for operand in &mut *operands {
187 self.erase_regions_operand(operand);
190 Rvalue::Slice { ref mut input, .. } => {
191 self.erase_regions_lvalue(input);
193 Rvalue::InlineAsm(_) => {},
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));
203 Literal::Value { .. } => { /* nothing to do */ }
207 fn erase_regions_return_ty(&mut self, fn_output: &mut ty::FnOutput<'tcx>) {
209 ty::FnConverging(ref mut ty) => {
210 *ty = self.tcx.erase_regions(ty);
212 ty::FnDiverging => {}
216 fn erase_regions_tys<'b, T>(&mut self, tys: T)
217 where T: Iterator<Item = &'b mut ty::Ty<'tcx>>,
221 *ty = self.tcx.erase_regions(ty);