@@ -13,10 +13,14 @@ use borrow_check::nll::type_check::AtLocation;
1313use dataflow:: move_paths:: { HasMoveData , MoveData } ;
1414use dataflow:: MaybeInitializedPlaces ;
1515use dataflow:: { FlowAtLocation , FlowsAtLocation } ;
16- use rustc:: infer:: InferOk ;
16+ use rustc:: infer:: region_constraints :: RegionConstraintData ;
1717use rustc:: mir:: Local ;
1818use rustc:: mir:: { BasicBlock , Location , Mir } ;
19- use rustc:: ty:: { Ty , TyCtxt , TypeFoldable } ;
19+ use rustc:: ty:: subst:: Kind ;
20+ use rustc:: ty:: { Ty , TypeFoldable } ;
21+ use rustc_data_structures:: fx:: FxHashMap ;
22+ use std:: rc:: Rc ;
23+ use syntax:: codemap:: DUMMY_SP ;
2024use util:: liveness:: LivenessResults ;
2125
2226use super :: TypeChecker ;
@@ -36,14 +40,13 @@ pub(super) fn generate<'gcx, 'tcx>(
3640 flow_inits : & mut FlowAtLocation < MaybeInitializedPlaces < ' _ , ' gcx , ' tcx > > ,
3741 move_data : & MoveData < ' tcx > ,
3842) {
39- let tcx = cx. tcx ( ) ;
4043 let mut generator = TypeLivenessGenerator {
4144 cx,
42- tcx,
4345 mir,
4446 liveness,
4547 flow_inits,
4648 move_data,
49+ drop_data : FxHashMap ( ) ,
4750 } ;
4851
4952 for bb in mir. basic_blocks ( ) . indices ( ) {
@@ -59,11 +62,16 @@ where
5962 ' gcx : ' tcx ,
6063{
6164 cx : & ' gen mut TypeChecker < ' typeck , ' gcx , ' tcx > ,
62- tcx : TyCtxt < ' typeck , ' gcx , ' tcx > ,
6365 mir : & ' gen Mir < ' tcx > ,
6466 liveness : & ' gen LivenessResults ,
6567 flow_inits : & ' gen mut FlowAtLocation < MaybeInitializedPlaces < ' flow , ' gcx , ' tcx > > ,
6668 move_data : & ' gen MoveData < ' tcx > ,
69+ drop_data : FxHashMap < Local , DropData < ' tcx > > ,
70+ }
71+
72+ struct DropData < ' tcx > {
73+ dropped_kinds : Vec < Kind < ' tcx > > ,
74+ region_constraint_data : Option < Rc < RegionConstraintData < ' tcx > > > ,
6775}
6876
6977impl < ' gen , ' typeck , ' flow , ' gcx , ' tcx > TypeLivenessGenerator < ' gen , ' typeck , ' flow , ' gcx , ' tcx > {
@@ -80,7 +88,7 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo
8088 for live_local in live_locals. iter ( ) {
8189 let live_local_ty = self . mir . local_decls [ live_local] . ty ;
8290 let cause = Cause :: LiveVar ( live_local, location) ;
83- self . push_type_live_constraint ( live_local_ty, location, cause) ;
91+ Self :: push_type_live_constraint ( & mut self . cx , live_local_ty, location, cause) ;
8492 }
8593 } ) ;
8694
@@ -148,17 +156,21 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo
148156 /// `location` -- i.e., it may be used later. This means that all
149157 /// regions appearing in the type `live_ty` must be live at
150158 /// `location`.
151- fn push_type_live_constraint < T > ( & mut self , value : T , location : Location , cause : Cause )
152- where
159+ fn push_type_live_constraint < T > (
160+ cx : & mut TypeChecker < ' _ , ' gcx , ' tcx > ,
161+ value : T ,
162+ location : Location ,
163+ cause : Cause ,
164+ ) where
153165 T : TypeFoldable < ' tcx > ,
154166 {
155167 debug ! (
156168 "push_type_live_constraint(live_ty={:?}, location={:?})" ,
157169 value, location
158170 ) ;
159171
160- self . tcx . for_each_free_region ( & value, |live_region| {
161- self . cx
172+ cx . tcx ( ) . for_each_free_region ( & value, |live_region| {
173+ cx
162174 . constraints
163175 . liveness_set
164176 . push ( ( live_region, location, cause. clone ( ) ) ) ;
@@ -182,53 +194,47 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo
182194 dropped_local, dropped_ty, location
183195 ) ;
184196
185- // If we end visiting the same type twice (usually due to a cycle involving
186- // associated types), we need to ensure that its region types match up with the type
187- // we added to the 'known' map the first time around. For this reason, we need
188- // our infcx to hold onto its calculated region constraints after each call
189- // to dtorck_constraint_for_ty. Otherwise, normalizing the corresponding associated
190- // type will end up instantiating the type with a new set of inference variables
191- // Since this new type will never be in 'known', we end up looping forever.
192- //
193- // For this reason, we avoid calling TypeChecker.normalize, instead doing all normalization
194- // ourselves in one large 'fully_perform_op' callback.
195- let kind_constraints = self
196- . cx
197- . fully_perform_op (
198- location. at_self ( ) ,
199- || format ! ( "add_drop_live_constraint(dropped_ty={:?})" , dropped_ty) ,
200- |cx| {
201- let span = cx. last_span ;
197+ let drop_data = self . drop_data . entry ( dropped_local) . or_insert_with ( {
198+ let cx = & mut self . cx ;
199+ move || Self :: compute_drop_data ( cx, dropped_ty)
200+ } ) ;
202201
203- let mut final_obligations = Vec :: new ( ) ;
204- let mut kind_constraints = Vec :: new ( ) ;
202+ if let Some ( data) = & drop_data. region_constraint_data {
203+ self . cx
204+ . push_region_constraints ( location. at_self ( ) , data. clone ( ) ) ;
205+ }
205206
206- let InferOk {
207- value : kinds,
208- obligations,
209- } = cx
207+ // All things in the `outlives` array may be touched by
208+ // the destructor and must be live at this point.
209+ let cause = Cause :: DropVar ( dropped_local, location) ;
210+ for & kind in & drop_data. dropped_kinds {
211+ Self :: push_type_live_constraint ( & mut self . cx , kind, location, cause) ;
212+ }
213+ }
214+
215+ #[ inline( never) ]
216+ fn compute_drop_data (
217+ cx : & mut TypeChecker < ' _ , ' gcx , ' tcx > ,
218+ dropped_ty : Ty < ' tcx > ,
219+ ) -> DropData < ' tcx > {
220+ debug ! ( "compute_drop_data(dropped_ty={:?})" , dropped_ty, ) ;
221+
222+ let ( dropped_kinds, region_constraint_data) =
223+ cx. fully_perform_op_and_get_region_constraint_data (
224+ || format ! ( "compute_drop_data(dropped_ty={:?})" , dropped_ty) ,
225+ |cx| {
226+ // crappy span, but I don't think it really matters
227+ let span = DUMMY_SP ;
228+ Ok ( cx
210229 . infcx
211230 . at ( & cx. misc ( span) , cx. param_env )
212- . dropck_outlives ( dropped_ty) ;
213- for kind in kinds {
214- // All things in the `outlives` array may be touched by
215- // the destructor and must be live at this point.
216- let cause = Cause :: DropVar ( dropped_local, location) ;
217- kind_constraints. push ( ( kind, location, cause) ) ;
218- }
219-
220- final_obligations. extend ( obligations) ;
221-
222- Ok ( InferOk {
223- value : kind_constraints,
224- obligations : final_obligations,
225- } )
231+ . dropck_outlives ( dropped_ty) )
226232 } ,
227- )
228- . unwrap ( ) ;
233+ ) . unwrap ( ) ;
229234
230- for ( kind, location, cause) in kind_constraints {
231- self . push_type_live_constraint ( kind, location, cause) ;
235+ DropData {
236+ dropped_kinds,
237+ region_constraint_data,
232238 }
233239 }
234240}
0 commit comments