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 rustc::mir::visit::MutVisitor;
18 use rustc::mir::mir_map::MirMap;
19 use rustc::mir::transform::MirPass;
21 pub fn erase_regions<'tcx>(tcx: &ty::ctxt<'tcx>, mir_map: &mut MirMap<'tcx>) {
22 let mut eraser = EraseRegions;
24 for (_, mir) in &mut mir_map.map {
25 eraser.run_on_mir(mir, tcx);
29 pub struct EraseRegions;
31 struct EraseRegionsVisitor<'a, 'tcx: 'a> {
32 tcx: &'a ty::ctxt<'tcx>,
35 impl<'a, 'tcx> EraseRegionsVisitor<'a, 'tcx> {
36 pub fn new(tcx: &'a ty::ctxt<'tcx>) -> Self {
42 fn erase_regions_return_ty(&mut self, fn_output: &mut ty::FnOutput<'tcx>) {
44 ty::FnConverging(ref mut ty) => {
45 *ty = self.tcx.erase_regions(ty);
51 fn erase_regions_tys<'b, T>(&mut self, tys: T)
52 where T: Iterator<Item = &'b mut ty::Ty<'tcx>>,
56 *ty = self.tcx.erase_regions(ty);
61 impl MirPass for EraseRegions {
62 fn run_on_mir<'tcx>(&mut self, mir: &mut Mir<'tcx>, tcx: &ty::ctxt<'tcx>) {
63 EraseRegionsVisitor::new(tcx).visit_mir(mir);
67 impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> {
68 fn visit_mir(&mut self, mir: &mut Mir<'tcx>) {
69 self.erase_regions_return_ty(&mut mir.return_ty);
70 self.erase_regions_tys(mir.var_decls.iter_mut().map(|d| &mut d.ty));
71 self.erase_regions_tys(mir.arg_decls.iter_mut().map(|d| &mut d.ty));
72 self.erase_regions_tys(mir.temp_decls.iter_mut().map(|d| &mut d.ty));
76 fn visit_terminator(&mut self, bb: BasicBlock, terminator: &mut Terminator<'tcx>) {
78 Terminator::Goto { .. } |
81 Terminator::If { .. } |
82 Terminator::Switch { .. } |
83 Terminator::Drop { .. } |
84 Terminator::Call { .. } => {
87 Terminator::SwitchInt { ref mut switch_ty, .. } => {
88 *switch_ty = self.tcx.erase_regions(switch_ty);
91 self.super_terminator(bb, terminator);
94 fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>) {
98 Rvalue::BinaryOp(_, _, _) |
99 Rvalue::UnaryOp(_, _) |
100 Rvalue::Slice { input: _, from_start: _, from_end: _ } |
101 Rvalue::InlineAsm(_) => {},
103 Rvalue::Repeat(_, ref mut value) => value.ty = self.tcx.erase_regions(&value.ty),
104 Rvalue::Ref(ref mut region, _, _) => *region = ty::ReStatic,
105 Rvalue::Cast(_, _, ref mut ty) => *ty = self.tcx.erase_regions(ty),
106 Rvalue::Box(ref mut ty) => *ty = self.tcx.erase_regions(ty),
109 Rvalue::Aggregate(AggregateKind::Vec, _) |
110 Rvalue::Aggregate(AggregateKind::Tuple, _) => {},
111 Rvalue::Aggregate(AggregateKind::Adt(_, _, ref mut substs), _) =>
112 *substs = self.tcx.mk_substs(self.tcx.erase_regions(*substs)),
113 Rvalue::Aggregate(AggregateKind::Closure(def_id, ref mut closure_substs), _) => {
114 let cloned = Box::new(closure_substs.clone());
115 let ty = self.tcx.mk_closure_from_closure_substs(def_id, cloned);
116 let erased = self.tcx.erase_regions(&ty);
117 *closure_substs = match erased.sty {
118 ty::TyClosure(_, ref closure_substs) => &*closure_substs,
123 self.super_rvalue(rvalue);
126 fn visit_constant(&mut self, constant: &mut Constant<'tcx>) {
127 constant.ty = self.tcx.erase_regions(&constant.ty);
128 match constant.literal {
129 Literal::Item { ref mut substs, .. } => {
130 *substs = self.tcx.mk_substs(self.tcx.erase_regions(substs));
132 Literal::Value { .. } => { /* nothing to do */ }
134 self.super_constant(constant);