8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- use rustc:: ty:: TyCtxt ;
12
- use rustc:: mir:: Mir ;
13
- use rustc:: mir:: visit:: MutVisitor ;
11
+ use rustc:: ty:: TypeFoldable ;
12
+ use rustc:: ty:: subst:: { Kind , Substs } ;
13
+ use rustc:: ty:: { Ty , TyCtxt , ClosureSubsts , RegionVid , RegionKind } ;
14
+ use rustc:: mir:: { Mir , Location , Rvalue , BasicBlock , Statement , StatementKind } ;
15
+ use rustc:: mir:: visit:: { MutVisitor , Lookup } ;
14
16
use rustc:: mir:: transform:: { MirPass , MirSource } ;
17
+ use rustc:: infer:: { self , InferCtxt } ;
18
+ use syntax_pos:: DUMMY_SP ;
19
+ use std:: collections:: HashMap ;
15
20
16
21
#[ allow( dead_code) ]
17
- struct NLLVisitor < ' a , ' tcx : ' a > {
18
- tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
22
+ struct NLLVisitor < ' a , ' gcx : ' a + ' tcx , ' tcx : ' a > {
23
+ lookup_map : HashMap < RegionVid , Lookup > ,
24
+ infcx : InferCtxt < ' a , ' gcx , ' tcx > ,
19
25
}
20
26
21
- impl < ' a , ' tcx > NLLVisitor < ' a , ' tcx > {
22
- pub fn new ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ) -> Self {
27
+ impl < ' a , ' gcx , ' tcx > NLLVisitor < ' a , ' gcx , ' tcx > {
28
+ pub fn new ( infcx : InferCtxt < ' a , ' gcx , ' tcx > ) -> Self {
23
29
NLLVisitor {
24
- tcx : tcx
30
+ infcx : infcx,
31
+ lookup_map : HashMap :: new ( ) ,
32
+ }
33
+ }
34
+
35
+ pub fn into_results ( self ) -> HashMap < RegionVid , Lookup > {
36
+ self . lookup_map
37
+ }
38
+
39
+ fn renumber_regions < T > ( & self , value : & T ) -> T where T : TypeFoldable < ' tcx > {
40
+ self . infcx . tcx . fold_regions ( value, & mut false , |_region, _depth| {
41
+ self . infcx . next_region_var ( infer:: MiscVariable ( DUMMY_SP ) )
42
+ } )
43
+ }
44
+
45
+ fn store_region ( & mut self , region : & RegionKind , lookup : Lookup ) {
46
+ if let RegionKind :: ReVar ( rid) = * region {
47
+ self . lookup_map . entry ( rid) . or_insert ( lookup) ;
48
+ }
49
+ }
50
+
51
+ fn store_ty_regions ( & mut self , ty : & Ty < ' tcx > , lookup : Lookup ) {
52
+ for region in ty. regions ( ) {
53
+ self . store_region ( region, lookup) ;
54
+ }
55
+ }
56
+
57
+ fn store_kind_regions ( & mut self , kind : & ' tcx Kind , lookup : Lookup ) {
58
+ if let Some ( ty) = kind. as_type ( ) {
59
+ self . store_ty_regions ( & ty, lookup) ;
60
+ } else if let Some ( region) = kind. as_region ( ) {
61
+ self . store_region ( region, lookup) ;
25
62
}
26
63
}
27
64
}
28
65
29
- impl < ' a , ' tcx > MutVisitor < ' tcx > for NLLVisitor < ' a , ' tcx > {
30
- // FIXME: Nashenas88: implement me!
66
+ impl < ' a , ' gcx , ' tcx > MutVisitor < ' tcx > for NLLVisitor < ' a , ' gcx , ' tcx > {
67
+ fn visit_ty ( & mut self , ty : & mut Ty < ' tcx > , lookup : Lookup ) {
68
+ let old_ty = * ty;
69
+ * ty = self . renumber_regions ( & old_ty) ;
70
+ self . store_ty_regions ( ty, lookup) ;
71
+ }
72
+
73
+ fn visit_substs ( & mut self , substs : & mut & ' tcx Substs < ' tcx > , location : Location ) {
74
+ * substs = self . renumber_regions ( & { * substs} ) ;
75
+ let lookup = Lookup :: Loc ( location) ;
76
+ for kind in * substs {
77
+ self . store_kind_regions ( kind, lookup) ;
78
+ }
79
+ }
80
+
81
+ fn visit_rvalue ( & mut self , rvalue : & mut Rvalue < ' tcx > , location : Location ) {
82
+ match * rvalue {
83
+ Rvalue :: Ref ( ref mut r, _, _) => {
84
+ let old_r = * r;
85
+ * r = self . renumber_regions ( & old_r) ;
86
+ let lookup = Lookup :: Loc ( location) ;
87
+ self . store_region ( r, lookup) ;
88
+ }
89
+ Rvalue :: Use ( ..) |
90
+ Rvalue :: Repeat ( ..) |
91
+ Rvalue :: Len ( ..) |
92
+ Rvalue :: Cast ( ..) |
93
+ Rvalue :: BinaryOp ( ..) |
94
+ Rvalue :: CheckedBinaryOp ( ..) |
95
+ Rvalue :: UnaryOp ( ..) |
96
+ Rvalue :: Discriminant ( ..) |
97
+ Rvalue :: NullaryOp ( ..) |
98
+ Rvalue :: Aggregate ( ..) => {
99
+ // These variants don't contain regions.
100
+ }
101
+ }
102
+ self . super_rvalue ( rvalue, location) ;
103
+ }
104
+
105
+ fn visit_closure_substs ( & mut self ,
106
+ substs : & mut ClosureSubsts < ' tcx > ,
107
+ location : Location ) {
108
+ * substs = self . renumber_regions ( substs) ;
109
+ let lookup = Lookup :: Loc ( location) ;
110
+ for kind in substs. substs {
111
+ self . store_kind_regions ( kind, lookup) ;
112
+ }
113
+ }
114
+
115
+ fn visit_statement ( & mut self ,
116
+ block : BasicBlock ,
117
+ statement : & mut Statement < ' tcx > ,
118
+ location : Location ) {
119
+ if let StatementKind :: EndRegion ( _) = statement. kind {
120
+ statement. kind = StatementKind :: Nop ;
121
+ }
122
+ self . super_statement ( block, statement, location) ;
123
+ }
31
124
}
32
125
33
126
// MIR Pass for non-lexical lifetimes
@@ -38,10 +131,16 @@ impl MirPass for NLL {
38
131
tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
39
132
_: MirSource ,
40
133
mir : & mut Mir < ' tcx > ) {
41
- if tcx. sess . opts . debugging_opts . nll {
42
- // Clone mir so we can mutate it without disturbing the rest
43
- // of the compiler
44
- NLLVisitor :: new ( tcx) . visit_mir ( & mut mir. clone ( ) ) ;
134
+ if !tcx. sess . opts . debugging_opts . nll {
135
+ return ;
45
136
}
137
+
138
+ tcx. infer_ctxt ( ) . enter ( |infcx| {
139
+ // Clone mir so we can mutate it without disturbing the rest of the compiler
140
+ let mut renumbered_mir = mir. clone ( ) ;
141
+ let mut visitor = NLLVisitor :: new ( infcx) ;
142
+ visitor. visit_mir ( & mut renumbered_mir) ;
143
+ let _results = visitor. into_results ( ) ;
144
+ } )
46
145
}
47
146
}
0 commit comments