9
9
// except according to those terms.
10
10
11
11
use rustc:: ty:: TypeFoldable ;
12
- use rustc:: ty:: subst:: Substs ;
13
- use rustc:: ty:: { Ty , TyCtxt , ClosureSubsts } ;
12
+ use rustc:: ty:: subst:: { Kind , Substs } ;
13
+ use rustc:: ty:: { Ty , TyCtxt , ClosureSubsts , RegionVid , RegionKind } ;
14
14
use rustc:: mir:: { Mir , Location , Rvalue , BasicBlock , Statement , StatementKind } ;
15
15
use rustc:: mir:: visit:: { MutVisitor , Lookup } ;
16
16
use rustc:: mir:: transform:: { MirPass , MirSource } ;
17
17
use rustc:: infer:: { self , InferCtxt } ;
18
- use syntax_pos:: Span ;
18
+ use syntax_pos:: DUMMY_SP ;
19
+ use std:: collections:: HashMap ;
19
20
20
21
#[ allow( dead_code) ]
21
22
struct NLLVisitor < ' a , ' gcx : ' a + ' tcx , ' tcx : ' a > {
23
+ pub lookup_map : HashMap < RegionVid , Lookup > ,
22
24
infcx : InferCtxt < ' a , ' gcx , ' tcx > ,
23
- source : & ' a Mir < ' tcx >
24
25
}
25
26
26
27
impl < ' a , ' gcx , ' tcx > NLLVisitor < ' a , ' gcx , ' tcx > {
27
- pub fn new ( infcx : InferCtxt < ' a , ' gcx , ' tcx > , source : & ' a Mir < ' tcx > ) -> Self {
28
+ pub fn new ( infcx : InferCtxt < ' a , ' gcx , ' tcx > ) -> Self {
28
29
NLLVisitor {
29
30
infcx : infcx,
30
- source : source ,
31
+ lookup_map : HashMap :: new ( ) ,
31
32
}
32
33
}
33
34
34
- fn renumber_regions < T > ( & self , value : & T , span : Span ) -> T where T : TypeFoldable < ' tcx > {
35
+ fn renumber_regions < T > ( & self , value : & T ) -> T where T : TypeFoldable < ' tcx > {
35
36
self . infcx . tcx . fold_regions ( value, & mut false , |_region, _depth| {
36
- self . infcx . next_region_var ( infer:: MiscVariable ( span ) )
37
+ self . infcx . next_region_var ( infer:: MiscVariable ( DUMMY_SP ) )
37
38
} )
38
39
}
39
- }
40
40
41
- fn span_from_location < ' tcx > ( source : & Mir < ' tcx > , location : Location ) -> Span {
42
- source[ location. block ] . statements [ location. statement_index ] . source_info . span
41
+ fn store_region ( & mut self , region : & RegionKind , lookup : Lookup ) {
42
+ if let RegionKind :: ReVar ( rid) = * region {
43
+ self . lookup_map . entry ( rid) . or_insert ( lookup) ;
44
+ }
45
+ }
46
+
47
+ fn store_ty_regions ( & mut self , ty : & Ty < ' tcx > , lookup : Lookup ) {
48
+ for region in ty. regions ( ) {
49
+ self . store_region ( region, lookup) ;
50
+ }
51
+ }
52
+
53
+ fn store_kind_regions ( & mut self , kind : & ' tcx Kind , lookup : Lookup ) {
54
+ if let Some ( ty) = kind. as_type ( ) {
55
+ self . store_ty_regions ( & ty, lookup) ;
56
+ } else if let Some ( region) = kind. as_region ( ) {
57
+ self . store_region ( region, lookup) ;
58
+ }
59
+ }
43
60
}
44
61
45
62
impl < ' a , ' gcx , ' tcx > MutVisitor < ' tcx > for NLLVisitor < ' a , ' gcx , ' tcx > {
46
63
fn visit_ty ( & mut self , ty : & mut Ty < ' tcx > , lookup : Lookup ) {
47
64
let old_ty = * ty;
48
- let span = match lookup {
49
- Lookup :: Loc ( location) => span_from_location ( self . source , location) ,
50
- Lookup :: Src ( source_info) => source_info. span ,
51
- } ;
52
- * ty = self . renumber_regions ( & old_ty, span) ;
65
+ * ty = self . renumber_regions ( & old_ty) ;
66
+ self . store_ty_regions ( ty, lookup) ;
53
67
}
54
68
55
69
fn visit_substs ( & mut self , substs : & mut & ' tcx Substs < ' tcx > , location : Location ) {
56
- * substs = self . renumber_regions ( & { * substs} , span_from_location ( self . source , location) ) ;
70
+ * substs = self . renumber_regions ( & { * substs} ) ;
71
+ let lookup = Lookup :: Loc ( location) ;
72
+ for kind in * substs {
73
+ self . store_kind_regions ( kind, lookup) ;
74
+ }
57
75
}
58
76
59
77
fn visit_rvalue ( & mut self , rvalue : & mut Rvalue < ' tcx > , location : Location ) {
60
78
match * rvalue {
61
79
Rvalue :: Ref ( ref mut r, _, _) => {
62
80
let old_r = * r;
63
- * r = self . renumber_regions ( & old_r, span_from_location ( self . source , location) ) ;
81
+ * r = self . renumber_regions ( & old_r) ;
82
+ let lookup = Lookup :: Loc ( location) ;
83
+ self . store_region ( r, lookup) ;
64
84
}
65
85
Rvalue :: Use ( ..) |
66
86
Rvalue :: Repeat ( ..) |
@@ -81,7 +101,11 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
81
101
fn visit_closure_substs ( & mut self ,
82
102
substs : & mut ClosureSubsts < ' tcx > ,
83
103
location : Location ) {
84
- * substs = self . renumber_regions ( substs, span_from_location ( self . source , location) ) ;
104
+ * substs = self . renumber_regions ( substs) ;
105
+ let lookup = Lookup :: Loc ( location) ;
106
+ for kind in substs. substs {
107
+ self . store_kind_regions ( kind, lookup) ;
108
+ }
85
109
}
86
110
87
111
fn visit_statement ( & mut self ,
@@ -108,14 +132,9 @@ impl MirPass for NLL {
108
132
}
109
133
110
134
tcx. infer_ctxt ( ) . enter ( |infcx| {
111
- // Clone mir so we can mutate it without disturbing the rest
112
- // of the compiler
135
+ // Clone mir so we can mutate it without disturbing the rest of the compiler
113
136
let mut renumbered_mir = mir. clone ( ) ;
114
-
115
- // Note that we're using the passed-in mir for the visitor. This is
116
- // so we can lookup locations during traversal without worrying about
117
- // maintaing both a mutable and immutable reference to the same object
118
- let mut visitor = NLLVisitor :: new ( infcx, & mir) ;
137
+ let mut visitor = NLLVisitor :: new ( infcx) ;
119
138
visitor. visit_mir ( & mut renumbered_mir) ;
120
139
} )
121
140
}
0 commit comments