1 // Copyright 2017 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 use rustc::ty::subst::Substs;
12 use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable};
13 use rustc::mir::{BasicBlock, Local, Location, Mir, Statement, StatementKind};
14 use rustc::mir::visit::{MutVisitor, TyContext};
15 use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
17 /// Replaces all free regions appearing in the MIR with fresh
18 /// inference variables, returning the number of variables created.
19 pub fn renumber_mir<'tcx>(infcx: &InferCtxt<'_, '_, 'tcx>, mir: &mut Mir<'tcx>) {
20 debug!("renumber_mir()");
21 debug!("renumber_mir: mir.arg_count={:?}", mir.arg_count);
23 let mut visitor = NLLVisitor { infcx };
24 visitor.visit_mir(mir);
27 /// Replaces all regions appearing in `value` with fresh inference
29 pub fn renumber_regions<'tcx, T>(
30 infcx: &InferCtxt<'_, '_, 'tcx>,
31 ty_context: TyContext,
35 T: TypeFoldable<'tcx>,
37 debug!("renumber_regions(value={:?})", value);
41 .fold_regions(value, &mut false, |_region, _depth| {
42 let origin = NLLRegionVariableOrigin::Inferred(ty_context);
43 infcx.next_nll_region_var(origin)
47 struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
48 infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
51 impl<'a, 'gcx, 'tcx> NLLVisitor<'a, 'gcx, 'tcx> {
52 fn renumber_regions<T>(&mut self, ty_context: TyContext, value: &T) -> T
54 T: TypeFoldable<'tcx>,
56 renumber_regions(self.infcx, ty_context, value)
60 impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
61 fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) {
62 debug!("visit_ty(ty={:?}, ty_context={:?})", ty, ty_context);
64 *ty = self.renumber_regions(ty_context, ty);
66 debug!("visit_ty: ty={:?}", ty);
69 fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, location: Location) {
70 debug!("visit_substs(substs={:?}, location={:?})", substs, location);
72 let ty_context = TyContext::Location(location);
73 *substs = self.renumber_regions(ty_context, &{ *substs });
75 debug!("visit_substs: substs={:?}", substs);
78 fn visit_region(&mut self, region: &mut ty::Region<'tcx>, location: Location) {
79 debug!("visit_region(region={:?}, location={:?})", region, location);
81 let old_region = *region;
82 let ty_context = TyContext::Location(location);
83 *region = self.renumber_regions(ty_context, &old_region);
85 debug!("visit_region: region={:?}", region);
88 fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, location: Location) {
89 let ty_context = TyContext::Location(location);
90 *constant = self.renumber_regions(ty_context, &*constant);
93 fn visit_generator_substs(&mut self,
94 substs: &mut GeneratorSubsts<'tcx>,
97 "visit_generator_substs(substs={:?}, location={:?})",
102 let ty_context = TyContext::Location(location);
103 *substs = self.renumber_regions(ty_context, substs);
105 debug!("visit_generator_substs: substs={:?}", substs);
108 fn visit_closure_substs(&mut self, substs: &mut ClosureSubsts<'tcx>, location: Location) {
110 "visit_closure_substs(substs={:?}, location={:?})",
115 let ty_context = TyContext::Location(location);
116 *substs = self.renumber_regions(ty_context, substs);
118 debug!("visit_closure_substs: substs={:?}", substs);
121 fn visit_user_assert_ty(&mut self, _c_ty: &mut CanonicalTy<'tcx>, _local: &mut Local,
122 _location: Location) {
123 // User-assert-ty statements represent types that the user added explicitly.
124 // We don't want to erase the regions from these types: rather, we want to
125 // add them as constraints at type-check time.
126 debug!("visit_user_assert_ty: skipping renumber");
132 statement: &mut Statement<'tcx>,
135 if let StatementKind::EndRegion(_) = statement.kind {
136 statement.kind = StatementKind::Nop;
138 self.super_statement(block, statement, location);