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