88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
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 } ;
1416use rustc:: mir:: transform:: { MirPass , MirSource } ;
17+ use rustc:: infer:: { self , InferCtxt } ;
18+ use syntax_pos:: DUMMY_SP ;
19+ use std:: collections:: HashMap ;
1520
1621#[ 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 > ,
1925}
2026
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 {
2329 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) ;
2562 }
2663 }
2764}
2865
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+ }
31124}
32125
33126// MIR Pass for non-lexical lifetimes
@@ -38,10 +131,16 @@ impl MirPass for NLL {
38131 tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
39132 _: MirSource ,
40133 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 ;
45136 }
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+ } )
46145 }
47146}
0 commit comments