88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11+ use borrow_check:: borrow_set:: BorrowSet ;
12+ use borrow_check:: location:: LocationTable ;
13+ use borrow_check:: nll:: facts:: AllFacts ;
1114use rustc:: hir;
12- use rustc:: mir:: { BasicBlock , BasicBlockData , Location , Place , Mir , Rvalue } ;
15+ use rustc:: infer:: InferCtxt ;
16+ use rustc:: mir:: visit:: TyContext ;
1317use rustc:: mir:: visit:: Visitor ;
1418use rustc:: mir:: Place :: Projection ;
15- use rustc:: mir:: { Local , PlaceProjection , ProjectionElem } ;
16- use rustc:: mir:: visit:: TyContext ;
17- use rustc:: infer:: InferCtxt ;
18- use rustc:: ty:: { self , CanonicalTy , ClosureSubsts } ;
19- use rustc:: ty:: subst:: Substs ;
19+ use rustc:: mir:: { BasicBlock , BasicBlockData , Location , Mir , Place , Rvalue } ;
20+ use rustc:: mir:: { Local , PlaceProjection , ProjectionElem , Statement , Terminator } ;
2021use rustc:: ty:: fold:: TypeFoldable ;
22+ use rustc:: ty:: subst:: Substs ;
23+ use rustc:: ty:: { self , CanonicalTy , ClosureSubsts } ;
2124
25+ use super :: region_infer:: { Cause , RegionInferenceContext } ;
2226use super :: ToRegionVid ;
23- use super :: region_infer:: { RegionInferenceContext , Cause } ;
2427
2528pub ( super ) fn generate_constraints < ' cx , ' gcx , ' tcx > (
2629 infcx : & InferCtxt < ' cx , ' gcx , ' tcx > ,
2730 regioncx : & mut RegionInferenceContext < ' tcx > ,
31+ all_facts : & mut Option < AllFacts > ,
32+ location_table : & LocationTable ,
2833 mir : & Mir < ' tcx > ,
34+ borrow_set : & BorrowSet < ' tcx > ,
2935) {
3036 let mut cg = ConstraintGeneration {
37+ borrow_set,
3138 infcx,
3239 regioncx,
40+ location_table,
41+ all_facts,
3342 mir,
3443 } ;
3544
@@ -41,8 +50,11 @@ pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
4150/// 'cg = the duration of the constraint generation process itself.
4251struct ConstraintGeneration < ' cg , ' cx : ' cg , ' gcx : ' tcx , ' tcx : ' cx > {
4352 infcx : & ' cg InferCtxt < ' cx , ' gcx , ' tcx > ,
53+ all_facts : & ' cg mut Option < AllFacts > ,
54+ location_table : & ' cg LocationTable ,
4455 regioncx : & ' cg mut RegionInferenceContext < ' tcx > ,
4556 mir : & ' cg Mir < ' tcx > ,
57+ borrow_set : & ' cg BorrowSet < ' tcx > ,
4658}
4759
4860impl < ' cg , ' cx , ' gcx , ' tcx > Visitor < ' tcx > for ConstraintGeneration < ' cg , ' cx , ' gcx , ' tcx > {
@@ -68,12 +80,14 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
6880 /// call. Make them live at the location where they appear.
6981 fn visit_ty ( & mut self , ty : & ty:: Ty < ' tcx > , ty_context : TyContext ) {
7082 match ty_context {
71- TyContext :: ReturnTy ( source_info) |
72- TyContext :: YieldTy ( source_info) |
73- TyContext :: LocalDecl { source_info, .. } => {
74- span_bug ! ( source_info. span,
75- "should not be visiting outside of the CFG: {:?}" ,
76- ty_context) ;
83+ TyContext :: ReturnTy ( source_info)
84+ | TyContext :: YieldTy ( source_info)
85+ | TyContext :: LocalDecl { source_info, .. } => {
86+ span_bug ! (
87+ source_info. span,
88+ "should not be visiting outside of the CFG: {:?}" ,
89+ ty_context
90+ ) ;
7791 }
7892 TyContext :: Location ( location) => {
7993 self . add_regular_live_constraint ( * ty, location, Cause :: LiveOther ( location) ) ;
@@ -90,25 +104,117 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
90104 self . super_closure_substs ( substs) ;
91105 }
92106
107+ fn visit_statement (
108+ & mut self ,
109+ block : BasicBlock ,
110+ statement : & Statement < ' tcx > ,
111+ location : Location ,
112+ ) {
113+ if let Some ( all_facts) = self . all_facts {
114+ all_facts. cfg_edge . push ( (
115+ self . location_table . start_index ( location) ,
116+ self . location_table . mid_index ( location) ,
117+ ) ) ;
118+
119+ all_facts. cfg_edge . push ( (
120+ self . location_table . mid_index ( location) ,
121+ self . location_table
122+ . start_index ( location. successor_within_block ( ) ) ,
123+ ) ) ;
124+ }
125+
126+ self . super_statement ( block, statement, location) ;
127+ }
128+
129+ fn visit_assign (
130+ & mut self ,
131+ block : BasicBlock ,
132+ place : & Place < ' tcx > ,
133+ rvalue : & Rvalue < ' tcx > ,
134+ location : Location ,
135+ ) {
136+ // When we see `X = ...`, then kill borrows of
137+ // `(*X).foo` and so forth.
138+ if let Some ( all_facts) = self . all_facts {
139+ if let Place :: Local ( temp) = place {
140+ if let Some ( borrow_indices) = self . borrow_set . local_map . get ( temp) {
141+ for & borrow_index in borrow_indices {
142+ let location_index = self . location_table . mid_index ( location) ;
143+ all_facts. killed . push ( ( borrow_index, location_index) ) ;
144+ }
145+ }
146+ }
147+ }
148+
149+ self . super_assign ( block, place, rvalue, location) ;
150+ }
151+
152+ fn visit_terminator (
153+ & mut self ,
154+ block : BasicBlock ,
155+ terminator : & Terminator < ' tcx > ,
156+ location : Location ,
157+ ) {
158+ if let Some ( all_facts) = self . all_facts {
159+ all_facts. cfg_edge . push ( (
160+ self . location_table . start_index ( location) ,
161+ self . location_table . mid_index ( location) ,
162+ ) ) ;
163+
164+ for successor_block in terminator. successors ( ) {
165+ all_facts. cfg_edge . push ( (
166+ self . location_table . mid_index ( location) ,
167+ self . location_table
168+ . start_index ( successor_block. start_location ( ) ) ,
169+ ) ) ;
170+ }
171+ }
172+
173+ self . super_terminator ( block, terminator, location) ;
174+ }
175+
93176 fn visit_rvalue ( & mut self , rvalue : & Rvalue < ' tcx > , location : Location ) {
94177 debug ! ( "visit_rvalue(rvalue={:?}, location={:?})" , rvalue, location) ;
95178
96- // Look for an rvalue like:
97- //
98- // & L
99- //
100- // where L is the path that is borrowed. In that case, we have
101- // to add the reborrow constraints (which don't fall out
102- // naturally from the type-checker).
103- if let Rvalue :: Ref ( region, _bk, ref borrowed_lv) = * rvalue {
104- self . add_reborrow_constraint ( location, region, borrowed_lv) ;
179+ match rvalue {
180+ Rvalue :: Ref ( region, _borrow_kind, borrowed_place) => {
181+ // In some cases, e.g. when borrowing from an unsafe
182+ // place, we don't bother to create a loan, since
183+ // there are no conditions to validate.
184+ if let Some ( all_facts) = self . all_facts {
185+ if let Some ( borrow_index) = self . borrow_set . location_map . get ( & location) {
186+ let region_vid = region. to_region_vid ( ) ;
187+ all_facts. borrow_region . push ( (
188+ region_vid,
189+ * borrow_index,
190+ self . location_table . mid_index ( location) ,
191+ ) ) ;
192+ }
193+ }
194+
195+ // Look for an rvalue like:
196+ //
197+ // & L
198+ //
199+ // where L is the path that is borrowed. In that case, we have
200+ // to add the reborrow constraints (which don't fall out
201+ // naturally from the type-checker).
202+ self . add_reborrow_constraint ( location, region, borrowed_place) ;
203+ }
204+
205+ _ => { }
105206 }
106207
107208 self . super_rvalue ( rvalue, location) ;
108209 }
109210
110- fn visit_user_assert_ty ( & mut self , _c_ty : & CanonicalTy < ' tcx > ,
111- _local : & Local , _location : Location ) { }
211+ fn visit_user_assert_ty (
212+ & mut self ,
213+ _c_ty : & CanonicalTy < ' tcx > ,
214+ _local : & Local ,
215+ _location : Location ,
216+ ) {
217+ }
112218}
113219
114220impl < ' cx , ' cg , ' gcx , ' tcx > ConstraintGeneration < ' cx , ' cg , ' gcx , ' tcx > {
@@ -122,8 +228,7 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
122228 {
123229 debug ! (
124230 "add_regular_live_constraint(live_ty={:?}, location={:?})" ,
125- live_ty,
126- location
231+ live_ty, location
127232 ) ;
128233
129234 self . infcx
@@ -144,8 +249,10 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
144249 ) {
145250 let mut borrowed_place = borrowed_place;
146251
147- debug ! ( "add_reborrow_constraint({:?}, {:?}, {:?})" ,
148- location, borrow_region, borrowed_place) ;
252+ debug ! (
253+ "add_reborrow_constraint({:?}, {:?}, {:?})" ,
254+ location, borrow_region, borrowed_place
255+ ) ;
149256 while let Projection ( box PlaceProjection { base, elem } ) = borrowed_place {
150257 debug ! ( "add_reborrow_constraint - iteration {:?}" , borrowed_place) ;
151258
@@ -165,12 +272,20 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
165272 location. successor_within_block ( ) ,
166273 ) ;
167274
275+ if let Some ( all_facts) = self . all_facts {
276+ all_facts. outlives . push ( (
277+ ref_region. to_region_vid ( ) ,
278+ borrow_region. to_region_vid ( ) ,
279+ self . location_table . mid_index ( location) ,
280+ ) ) ;
281+ }
282+
168283 match mutbl {
169284 hir:: Mutability :: MutImmutable => {
170285 // Immutable reference. We don't need the base
171286 // to be valid for the entire lifetime of
172287 // the borrow.
173- break
288+ break ;
174289 }
175290 hir:: Mutability :: MutMutable => {
176291 // Mutable reference. We *do* need the base
@@ -199,19 +314,19 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
199314 }
200315 ty:: TyRawPtr ( ..) => {
201316 // deref of raw pointer, guaranteed to be valid
202- break
317+ break ;
203318 }
204319 ty:: TyAdt ( def, _) if def. is_box ( ) => {
205320 // deref of `Box`, need the base to be valid - propagate
206321 }
207- _ => bug ! ( "unexpected deref ty {:?} in {:?}" , base_ty, borrowed_place)
322+ _ => bug ! ( "unexpected deref ty {:?} in {:?}" , base_ty, borrowed_place) ,
208323 }
209324 }
210- ProjectionElem :: Field ( ..) |
211- ProjectionElem :: Downcast ( ..) |
212- ProjectionElem :: Index ( ..) |
213- ProjectionElem :: ConstantIndex { .. } |
214- ProjectionElem :: Subslice { .. } => {
325+ ProjectionElem :: Field ( ..)
326+ | ProjectionElem :: Downcast ( ..)
327+ | ProjectionElem :: Index ( ..)
328+ | ProjectionElem :: ConstantIndex { .. }
329+ | ProjectionElem :: Subslice { .. } => {
215330 // other field access
216331 }
217332 }
0 commit comments