]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/transform/erase_regions.rs
Auto merge of #31278 - alexcrichton:print-cfg, 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 rustc::mir::visit::MutVisitor;
18 use mir_map::MirMap;
19 use transform::MirPass;
20
21 pub fn erase_regions<'tcx>(tcx: &ty::ctxt<'tcx>, mir_map: &mut MirMap<'tcx>) {
22     let mut eraser = EraseRegions::new(tcx);
23
24     for mir in mir_map.iter_mut().map(|(_, v)| v) {
25         eraser.run_on_mir(mir);
26     }
27 }
28
29 pub struct EraseRegions<'a, 'tcx: 'a> {
30     tcx: &'a ty::ctxt<'tcx>,
31 }
32
33 impl<'a, 'tcx> EraseRegions<'a, 'tcx> {
34     pub fn new(tcx: &'a ty::ctxt<'tcx>) -> EraseRegions<'a, 'tcx> {
35         EraseRegions {
36             tcx: tcx
37         }
38     }
39
40     fn erase_regions_return_ty(&mut self, fn_output: &mut ty::FnOutput<'tcx>) {
41         match *fn_output {
42             ty::FnConverging(ref mut ty) => {
43                 *ty = self.tcx.erase_regions(ty);
44             },
45             ty::FnDiverging => {}
46         }
47     }
48
49     fn erase_regions_tys<'b, T>(&mut self, tys: T)
50         where T: Iterator<Item = &'b mut ty::Ty<'tcx>>,
51               'tcx: 'b
52     {
53         for ty in tys {
54             *ty = self.tcx.erase_regions(ty);
55         }
56     }
57 }
58
59 impl<'a, 'tcx> MirPass<'tcx> for EraseRegions<'a, 'tcx> {
60     fn run_on_mir(&mut self, mir: &mut Mir<'tcx>) {
61         self.visit_mir(mir);
62     }
63 }
64
65 impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegions<'a, 'tcx> {
66     fn visit_mir(&mut self, mir: &mut Mir<'tcx>) {
67         self.erase_regions_return_ty(&mut mir.return_ty);
68         self.erase_regions_tys(mir.var_decls.iter_mut().map(|d| &mut d.ty));
69         self.erase_regions_tys(mir.arg_decls.iter_mut().map(|d| &mut d.ty));
70         self.erase_regions_tys(mir.temp_decls.iter_mut().map(|d| &mut d.ty));
71         self.super_mir(mir);
72     }
73
74     fn visit_terminator(&mut self, bb: BasicBlock, terminator: &mut Terminator<'tcx>) {
75         match *terminator {
76             Terminator::Goto { .. } |
77             Terminator::Resume |
78             Terminator::Return |
79             Terminator::If { .. } |
80             Terminator::Switch { .. } |
81             Terminator::Drop { .. } |
82             Terminator::Call { .. } => {
83                 /* nothing to do */
84             },
85             Terminator::SwitchInt { ref mut switch_ty, .. } => {
86                 *switch_ty = self.tcx.erase_regions(switch_ty);
87             },
88         }
89         self.super_terminator(bb, terminator);
90     }
91
92     fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>) {
93         match *rvalue {
94             Rvalue::Use(_) |
95             Rvalue::Len(_) |
96             Rvalue::BinaryOp(_, _, _) |
97             Rvalue::UnaryOp(_, _) |
98             Rvalue::Slice { input: _, from_start: _, from_end: _ } |
99             Rvalue::InlineAsm(_) => {},
100
101             Rvalue::Repeat(_, ref mut value) => value.ty = self.tcx.erase_regions(&value.ty),
102             Rvalue::Ref(ref mut region, _, _) => *region = ty::ReStatic,
103             Rvalue::Cast(_, _, ref mut ty) => *ty = self.tcx.erase_regions(ty),
104             Rvalue::Box(ref mut ty) => *ty = self.tcx.erase_regions(ty),
105
106
107             Rvalue::Aggregate(AggregateKind::Vec, _) |
108             Rvalue::Aggregate(AggregateKind::Tuple, _) => {},
109             Rvalue::Aggregate(AggregateKind::Adt(_, _, ref mut substs), _) =>
110                 *substs = self.tcx.mk_substs(self.tcx.erase_regions(*substs)),
111             Rvalue::Aggregate(AggregateKind::Closure(def_id, ref mut closure_substs), _) => {
112                 let cloned = Box::new(closure_substs.clone());
113                 let ty = self.tcx.mk_closure_from_closure_substs(def_id, cloned);
114                 let erased = self.tcx.erase_regions(&ty);
115                 *closure_substs = match erased.sty {
116                     ty::TyClosure(_, ref closure_substs) => &*closure_substs,
117                     _ => unreachable!()
118                 };
119             }
120         }
121         self.super_rvalue(rvalue);
122     }
123
124     fn visit_constant(&mut self, constant: &mut Constant<'tcx>) {
125         constant.ty = self.tcx.erase_regions(&constant.ty);
126         match constant.literal {
127             Literal::Item { ref mut substs, .. } => {
128                 *substs = self.tcx.mk_substs(self.tcx.erase_regions(substs));
129             }
130             Literal::Value { .. } => { /* nothing to do */ }
131         }
132         self.super_constant(constant);
133     }
134 }