@@ -15,7 +15,11 @@ use dataflow::move_paths::{HasMoveData, MoveData};
1515use rustc:: mir:: { BasicBlock , Location , Mir } ;
1616use rustc:: mir:: Local ;
1717use rustc:: ty:: { self , Ty , TyCtxt , TypeFoldable } ;
18+ //use rustc::ty::subst::Kind;
19+ use rustc:: traits;
20+ use rustc:: infer:: InferOk ;
1821use rustc:: util:: common:: ErrorReported ;
22+ use borrow_check:: nll:: type_check:: AtLocation ;
1923use rustc_data_structures:: fx:: FxHashSet ;
2024use syntax:: codemap:: DUMMY_SP ;
2125use util:: liveness:: LivenessResults ;
@@ -184,48 +188,87 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo
184188 location
185189 ) ;
186190
187- let tcx = self . cx . infcx . tcx ;
188- let mut types = vec ! [ ( dropped_ty, 0 ) ] ;
189- let mut known = FxHashSet ( ) ;
190- while let Some ( ( ty, depth) ) = types. pop ( ) {
191- let span = DUMMY_SP ; // FIXME
192- let result = match tcx. dtorck_constraint_for_ty ( span, dropped_ty, depth, ty) {
193- Ok ( result) => result,
194- Err ( ErrorReported ) => {
195- continue ;
196- }
197- } ;
198-
199- let ty:: DtorckConstraint {
200- outlives,
201- dtorck_types,
202- } = result;
203-
204- // All things in the `outlives` array may be touched by
205- // the destructor and must be live at this point.
206- for outlive in outlives {
207- let cause = Cause :: DropVar ( dropped_local, location) ;
208- self . push_type_live_constraint ( outlive, location, cause) ;
209- }
191+ // If we end visiting the same type twice (usually due to a cycle involving
192+ // associated types), we need to ensure that its region types match up with the type
193+ // we added to the 'known' map the first time around. For this reason, we need
194+ // our infcx to hold onto its calculated region constraints after each call
195+ // to dtorck_constraint_for_ty. Otherwise, normalizing the corresponding associated
196+ // type will end up instantiating the type with a new set of inference variables
197+ // Since this new type will never be in 'known', we end up looping forever.
198+ //
199+ // For this reason, we avoid calling TypeChecker.normalize, instead doing all normalization
200+ // ourselves in one large 'fully_perform_op' callback.
201+ let ( type_constraints, kind_constraints) = self . cx . fully_perform_op ( location. at_self ( ) ,
202+ |cx| {
203+
204+ let tcx = cx. infcx . tcx ;
205+ let mut selcx = traits:: SelectionContext :: new ( cx. infcx ) ;
206+ let cause = cx. misc ( cx. last_span ) ;
207+
208+ let mut types = vec ! [ ( dropped_ty, 0 ) ] ;
209+ let mut final_obligations = Vec :: new ( ) ;
210+ let mut type_constraints = Vec :: new ( ) ;
211+ let mut kind_constraints = Vec :: new ( ) ;
210212
211- // However, there may also be some types that
212- // `dtorck_constraint_for_ty` could not resolve (e.g.,
213- // associated types and parameters). We need to normalize
214- // associated types here and possibly recursively process.
215- for ty in dtorck_types {
216- let ty = self . cx . normalize ( & ty, location) ;
217- let ty = self . cx . infcx . resolve_type_and_region_vars_if_possible ( & ty) ;
218- match ty. sty {
219- ty:: TyParam ( ..) | ty:: TyProjection ( ..) | ty:: TyAnon ( ..) => {
220- let cause = Cause :: DropVar ( dropped_local, location) ;
221- self . push_type_live_constraint ( ty, location, cause) ;
213+ let mut known = FxHashSet ( ) ;
214+
215+ while let Some ( ( ty, depth) ) = types. pop ( ) {
216+ let span = DUMMY_SP ; // FIXME
217+ let result = match tcx. dtorck_constraint_for_ty ( span, dropped_ty, depth, ty) {
218+ Ok ( result) => result,
219+ Err ( ErrorReported ) => {
220+ continue ;
222221 }
222+ } ;
223+
224+ let ty:: DtorckConstraint {
225+ outlives,
226+ dtorck_types,
227+ } = result;
228+
229+ // All things in the `outlives` array may be touched by
230+ // the destructor and must be live at this point.
231+ for outlive in outlives {
232+ let cause = Cause :: DropVar ( dropped_local, location) ;
233+ kind_constraints. push ( ( outlive, location, cause) ) ;
234+ }
223235
224- _ => if known. insert ( ty) {
225- types. push ( ( ty, depth + 1 ) ) ;
226- } ,
236+ // However, there may also be some types that
237+ // `dtorck_constraint_for_ty` could not resolve (e.g.,
238+ // associated types and parameters). We need to normalize
239+ // associated types here and possibly recursively process.
240+ for ty in dtorck_types {
241+ let traits:: Normalized { value : ty, obligations } =
242+ traits:: normalize ( & mut selcx, cx. param_env , cause. clone ( ) , & ty) ;
243+
244+ final_obligations. extend ( obligations) ;
245+
246+ //let ty = self.cx.normalize(&ty, location);
247+ let ty = cx. infcx . resolve_type_and_region_vars_if_possible ( & ty) ;
248+ match ty. sty {
249+ ty:: TyParam ( ..) | ty:: TyProjection ( ..) | ty:: TyAnon ( ..) => {
250+ let cause = Cause :: DropVar ( dropped_local, location) ;
251+ type_constraints. push ( ( ty, location, cause) ) ;
252+ }
253+
254+ _ => if known. insert ( ty) {
255+ types. push ( ( ty, depth + 1 ) ) ;
256+ } ,
257+ }
227258 }
228259 }
260+
261+ Ok ( InferOk {
262+ value : ( type_constraints, kind_constraints) , obligations : final_obligations
263+ } )
264+ } ) . unwrap ( ) ;
265+
266+ for ( ty, location, cause) in type_constraints {
267+ self . push_type_live_constraint ( ty, location, cause) ;
268+ }
269+
270+ for ( kind, location, cause) in kind_constraints {
271+ self . push_type_live_constraint ( kind, location, cause) ;
229272 }
230273 }
231274}
0 commit comments