2015-11-16 11:41:16 -06:00
|
|
|
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
|
|
|
//! This pass erases all early-bound regions from the types occuring in the MIR.
|
|
|
|
//! We want to do this once just before trans, so trans does not have to take
|
|
|
|
//! care erasing regions all over the place.
|
|
|
|
|
2016-02-29 17:36:51 -06:00
|
|
|
use rustc::middle::ty::{self, TyCtxt};
|
2015-11-19 09:37:34 -06:00
|
|
|
use rustc::mir::repr::*;
|
2016-01-31 12:25:17 -06:00
|
|
|
use rustc::mir::visit::MutVisitor;
|
2016-02-05 02:32:33 -06:00
|
|
|
use rustc::mir::mir_map::MirMap;
|
2015-11-16 11:41:16 -06:00
|
|
|
|
2016-02-29 17:36:51 -06:00
|
|
|
pub fn erase_regions<'tcx>(tcx: &TyCtxt<'tcx>, mir_map: &mut MirMap<'tcx>) {
|
2016-02-05 02:32:33 -06:00
|
|
|
for (_, mir) in &mut mir_map.map {
|
2016-02-12 16:23:16 -06:00
|
|
|
EraseRegionsVisitor::new(tcx).visit_mir(mir);
|
2015-11-16 11:41:16 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-05 02:35:00 -06:00
|
|
|
struct EraseRegionsVisitor<'a, 'tcx: 'a> {
|
2016-02-29 17:36:51 -06:00
|
|
|
tcx: &'a TyCtxt<'tcx>,
|
2015-11-16 11:41:16 -06:00
|
|
|
}
|
|
|
|
|
2016-02-05 02:35:00 -06:00
|
|
|
impl<'a, 'tcx> EraseRegionsVisitor<'a, 'tcx> {
|
2016-02-29 17:36:51 -06:00
|
|
|
pub fn new(tcx: &'a TyCtxt<'tcx>) -> Self {
|
2016-02-05 02:35:00 -06:00
|
|
|
EraseRegionsVisitor {
|
2015-11-16 11:41:16 -06:00
|
|
|
tcx: tcx
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-31 12:25:17 -06:00
|
|
|
fn erase_regions_return_ty(&mut self, fn_output: &mut ty::FnOutput<'tcx>) {
|
|
|
|
match *fn_output {
|
|
|
|
ty::FnConverging(ref mut ty) => {
|
|
|
|
*ty = self.tcx.erase_regions(ty);
|
|
|
|
},
|
|
|
|
ty::FnDiverging => {}
|
2015-11-16 11:41:16 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-31 12:25:17 -06:00
|
|
|
fn erase_regions_tys<'b, T>(&mut self, tys: T)
|
|
|
|
where T: Iterator<Item = &'b mut ty::Ty<'tcx>>,
|
|
|
|
'tcx: 'b
|
|
|
|
{
|
|
|
|
for ty in tys {
|
|
|
|
*ty = self.tcx.erase_regions(ty);
|
2015-11-16 11:41:16 -06:00
|
|
|
}
|
|
|
|
}
|
2016-01-31 12:25:17 -06:00
|
|
|
}
|
|
|
|
|
2016-02-05 02:35:00 -06:00
|
|
|
impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> {
|
2016-01-31 12:25:17 -06:00
|
|
|
fn visit_mir(&mut self, mir: &mut Mir<'tcx>) {
|
|
|
|
self.erase_regions_return_ty(&mut mir.return_ty);
|
|
|
|
self.erase_regions_tys(mir.var_decls.iter_mut().map(|d| &mut d.ty));
|
|
|
|
self.erase_regions_tys(mir.arg_decls.iter_mut().map(|d| &mut d.ty));
|
|
|
|
self.erase_regions_tys(mir.temp_decls.iter_mut().map(|d| &mut d.ty));
|
|
|
|
self.super_mir(mir);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_terminator(&mut self, bb: BasicBlock, terminator: &mut Terminator<'tcx>) {
|
2015-11-16 11:41:16 -06:00
|
|
|
match *terminator {
|
|
|
|
Terminator::Goto { .. } |
|
2015-12-15 12:46:39 -06:00
|
|
|
Terminator::Resume |
|
2016-01-31 12:25:17 -06:00
|
|
|
Terminator::Return |
|
|
|
|
Terminator::If { .. } |
|
|
|
|
Terminator::Switch { .. } |
|
|
|
|
Terminator::Drop { .. } |
|
|
|
|
Terminator::Call { .. } => {
|
2015-11-16 11:41:16 -06:00
|
|
|
/* nothing to do */
|
2016-01-31 12:25:17 -06:00
|
|
|
},
|
|
|
|
Terminator::SwitchInt { ref mut switch_ty, .. } => {
|
2015-11-16 11:41:16 -06:00
|
|
|
*switch_ty = self.tcx.erase_regions(switch_ty);
|
|
|
|
},
|
|
|
|
}
|
2016-01-31 12:25:17 -06:00
|
|
|
self.super_terminator(bb, terminator);
|
2015-11-16 11:41:16 -06:00
|
|
|
}
|
|
|
|
|
2016-01-31 12:25:17 -06:00
|
|
|
fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>) {
|
2015-11-16 11:41:16 -06:00
|
|
|
match *rvalue {
|
2016-01-31 12:25:17 -06:00
|
|
|
Rvalue::Use(_) |
|
|
|
|
Rvalue::Len(_) |
|
|
|
|
Rvalue::BinaryOp(_, _, _) |
|
|
|
|
Rvalue::UnaryOp(_, _) |
|
|
|
|
Rvalue::Slice { input: _, from_start: _, from_end: _ } |
|
|
|
|
Rvalue::InlineAsm(_) => {},
|
|
|
|
|
|
|
|
Rvalue::Repeat(_, ref mut value) => value.ty = self.tcx.erase_regions(&value.ty),
|
|
|
|
Rvalue::Ref(ref mut region, _, _) => *region = ty::ReStatic,
|
|
|
|
Rvalue::Cast(_, _, ref mut ty) => *ty = self.tcx.erase_regions(ty),
|
2015-11-16 11:41:16 -06:00
|
|
|
Rvalue::Box(ref mut ty) => *ty = self.tcx.erase_regions(ty),
|
2016-01-31 12:25:17 -06:00
|
|
|
|
|
|
|
|
|
|
|
Rvalue::Aggregate(AggregateKind::Vec, _) |
|
|
|
|
Rvalue::Aggregate(AggregateKind::Tuple, _) => {},
|
|
|
|
Rvalue::Aggregate(AggregateKind::Adt(_, _, ref mut substs), _) =>
|
|
|
|
*substs = self.tcx.mk_substs(self.tcx.erase_regions(*substs)),
|
|
|
|
Rvalue::Aggregate(AggregateKind::Closure(def_id, ref mut closure_substs), _) => {
|
|
|
|
let cloned = Box::new(closure_substs.clone());
|
|
|
|
let ty = self.tcx.mk_closure_from_closure_substs(def_id, cloned);
|
|
|
|
let erased = self.tcx.erase_regions(&ty);
|
|
|
|
*closure_substs = match erased.sty {
|
|
|
|
ty::TyClosure(_, ref closure_substs) => &*closure_substs,
|
|
|
|
_ => unreachable!()
|
|
|
|
};
|
2015-11-16 11:41:16 -06:00
|
|
|
}
|
|
|
|
}
|
2016-01-31 12:25:17 -06:00
|
|
|
self.super_rvalue(rvalue);
|
2015-11-16 11:41:16 -06:00
|
|
|
}
|
|
|
|
|
2016-01-31 12:25:17 -06:00
|
|
|
fn visit_constant(&mut self, constant: &mut Constant<'tcx>) {
|
2015-11-16 11:41:16 -06:00
|
|
|
constant.ty = self.tcx.erase_regions(&constant.ty);
|
|
|
|
match constant.literal {
|
|
|
|
Literal::Item { ref mut substs, .. } => {
|
|
|
|
*substs = self.tcx.mk_substs(self.tcx.erase_regions(substs));
|
|
|
|
}
|
|
|
|
Literal::Value { .. } => { /* nothing to do */ }
|
|
|
|
}
|
2016-01-31 12:25:17 -06:00
|
|
|
self.super_constant(constant);
|
2015-11-16 11:41:16 -06:00
|
|
|
}
|
|
|
|
}
|