]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/borrow_check/nll/renumber.rs
make liveness generic over set of local variables
[rust.git] / src / librustc_mir / borrow_check / nll / renumber.rs
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.
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 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};
16
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);
22
23     let mut visitor = NLLVisitor { infcx };
24     visitor.visit_mir(mir);
25 }
26
27 /// Replaces all regions appearing in `value` with fresh inference
28 /// variables.
29 pub fn renumber_regions<'tcx, T>(
30     infcx: &InferCtxt<'_, '_, 'tcx>,
31     ty_context: TyContext,
32     value: &T,
33 ) -> T
34 where
35     T: TypeFoldable<'tcx>,
36 {
37     debug!("renumber_regions(value={:?})", value);
38
39     infcx
40         .tcx
41         .fold_regions(value, &mut false, |_region, _depth| {
42             let origin = NLLRegionVariableOrigin::Inferred(ty_context);
43             infcx.next_nll_region_var(origin)
44         })
45 }
46
47 struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
48     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
49 }
50
51 impl<'a, 'gcx, 'tcx> NLLVisitor<'a, 'gcx, 'tcx> {
52     fn renumber_regions<T>(&mut self, ty_context: TyContext, value: &T) -> T
53     where
54         T: TypeFoldable<'tcx>,
55     {
56         renumber_regions(self.infcx, ty_context, value)
57     }
58 }
59
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);
63
64         *ty = self.renumber_regions(ty_context, ty);
65
66         debug!("visit_ty: ty={:?}", ty);
67     }
68
69     fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, location: Location) {
70         debug!("visit_substs(substs={:?}, location={:?})", substs, location);
71
72         let ty_context = TyContext::Location(location);
73         *substs = self.renumber_regions(ty_context, &{ *substs });
74
75         debug!("visit_substs: substs={:?}", substs);
76     }
77
78     fn visit_region(&mut self, region: &mut ty::Region<'tcx>, location: Location) {
79         debug!("visit_region(region={:?}, location={:?})", region, location);
80
81         let old_region = *region;
82         let ty_context = TyContext::Location(location);
83         *region = self.renumber_regions(ty_context, &old_region);
84
85         debug!("visit_region: region={:?}", region);
86     }
87
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);
91     }
92
93     fn visit_generator_substs(&mut self,
94                               substs: &mut GeneratorSubsts<'tcx>,
95                               location: Location) {
96         debug!(
97             "visit_generator_substs(substs={:?}, location={:?})",
98             substs,
99             location,
100         );
101
102         let ty_context = TyContext::Location(location);
103         *substs = self.renumber_regions(ty_context, substs);
104
105         debug!("visit_generator_substs: substs={:?}", substs);
106     }
107
108     fn visit_closure_substs(&mut self, substs: &mut ClosureSubsts<'tcx>, location: Location) {
109         debug!(
110             "visit_closure_substs(substs={:?}, location={:?})",
111             substs,
112             location
113         );
114
115         let ty_context = TyContext::Location(location);
116         *substs = self.renumber_regions(ty_context, substs);
117
118         debug!("visit_closure_substs: substs={:?}", substs);
119     }
120
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");
127     }
128
129     fn visit_statement(
130         &mut self,
131         block: BasicBlock,
132         statement: &mut Statement<'tcx>,
133         location: Location,
134     ) {
135         if let StatementKind::EndRegion(_) = statement.kind {
136             statement.kind = StatementKind::Nop;
137         }
138         self.super_statement(block, statement, location);
139     }
140 }