@@ -28,6 +28,7 @@ use crate::traits::{Obligation, PredicateObligations};
2828use rustc_data_structures:: fx:: FxHashMap ;
2929use rustc_middle:: traits:: ObligationCause ;
3030use rustc_middle:: ty:: error:: TypeError ;
31+ use rustc_middle:: ty:: fold:: FnMutDelegate ;
3132use rustc_middle:: ty:: relate:: { self , Relate , RelateResult , TypeRelation } ;
3233use rustc_middle:: ty:: visit:: { TypeSuperVisitable , TypeVisitable , TypeVisitableExt , TypeVisitor } ;
3334use rustc_middle:: ty:: { self , InferConst , Ty , TyCtxt } ;
5556 ambient_variance : ty:: Variance ,
5657
5758 ambient_variance_info : ty:: VarianceDiagInfo < ' tcx > ,
58-
59- /// When we pass through a set of binders (e.g., when looking into
60- /// a `fn` type), we push a new bound region scope onto here. This
61- /// will contain the instantiated region for each region in those
62- /// binders. When we then encounter a `ReLateBound(d, br)`, we can
63- /// use the De Bruijn index `d` to find the right scope, and then
64- /// bound region name `br` to find the specific instantiation from
65- /// within that scope. See `replace_bound_region`.
66- ///
67- /// This field stores the instantiations for late-bound regions in
68- /// the `a` type.
69- a_scopes : Vec < BoundRegionScope < ' tcx > > ,
70-
71- /// Same as `a_scopes`, but for the `b` type.
72- b_scopes : Vec < BoundRegionScope < ' tcx > > ,
7359}
7460
7561pub trait TypeRelatingDelegate < ' tcx > {
@@ -147,8 +133,6 @@ where
147133 delegate,
148134 ambient_variance,
149135 ambient_variance_info : ty:: VarianceDiagInfo :: default ( ) ,
150- a_scopes : vec ! [ ] ,
151- b_scopes : vec ! [ ] ,
152136 }
153137 }
154138
@@ -166,88 +150,6 @@ where
166150 }
167151 }
168152
169- fn create_scope (
170- & mut self ,
171- value : ty:: Binder < ' tcx , impl Relate < ' tcx > > ,
172- universally_quantified : UniversallyQuantified ,
173- ) -> BoundRegionScope < ' tcx > {
174- let mut scope = BoundRegionScope :: default ( ) ;
175-
176- // Create a callback that creates (via the delegate) either an
177- // existential or placeholder region as needed.
178- let mut next_region = {
179- let delegate = & mut self . delegate ;
180- let mut lazy_universe = None ;
181- move |br : ty:: BoundRegion | {
182- if universally_quantified. 0 {
183- // The first time this closure is called, create a
184- // new universe for the placeholders we will make
185- // from here out.
186- let universe = lazy_universe. unwrap_or_else ( || {
187- let universe = delegate. create_next_universe ( ) ;
188- lazy_universe = Some ( universe) ;
189- universe
190- } ) ;
191-
192- let placeholder = ty:: PlaceholderRegion { universe, name : br. kind } ;
193- delegate. next_placeholder_region ( placeholder)
194- } else {
195- delegate. next_existential_region_var ( true , br. kind . get_name ( ) )
196- }
197- }
198- } ;
199-
200- value. skip_binder ( ) . visit_with ( & mut ScopeInstantiator {
201- next_region : & mut next_region,
202- target_index : ty:: INNERMOST ,
203- bound_region_scope : & mut scope,
204- } ) ;
205-
206- scope
207- }
208-
209- /// When we encounter binders during the type traversal, we record
210- /// the value to substitute for each of the things contained in
211- /// that binder. (This will be either a universal placeholder or
212- /// an existential inference variable.) Given the De Bruijn index
213- /// `debruijn` (and name `br`) of some binder we have now
214- /// encountered, this routine finds the value that we instantiated
215- /// the region with; to do so, it indexes backwards into the list
216- /// of ambient scopes `scopes`.
217- fn lookup_bound_region (
218- debruijn : ty:: DebruijnIndex ,
219- br : & ty:: BoundRegion ,
220- first_free_index : ty:: DebruijnIndex ,
221- scopes : & [ BoundRegionScope < ' tcx > ] ,
222- ) -> ty:: Region < ' tcx > {
223- // The debruijn index is a "reverse index" into the
224- // scopes listing. So when we have INNERMOST (0), we
225- // want the *last* scope pushed, and so forth.
226- let debruijn_index = debruijn. index ( ) - first_free_index. index ( ) ;
227- let scope = & scopes[ scopes. len ( ) - debruijn_index - 1 ] ;
228-
229- // Find this bound region in that scope to map to a
230- // particular region.
231- scope. map [ br]
232- }
233-
234- /// If `r` is a bound region, find the scope in which it is bound
235- /// (from `scopes`) and return the value that we instantiated it
236- /// with. Otherwise just return `r`.
237- fn replace_bound_region (
238- & self ,
239- r : ty:: Region < ' tcx > ,
240- first_free_index : ty:: DebruijnIndex ,
241- scopes : & [ BoundRegionScope < ' tcx > ] ,
242- ) -> ty:: Region < ' tcx > {
243- debug ! ( "replace_bound_regions(scopes={:?})" , scopes) ;
244- if let ty:: ReLateBound ( debruijn, br) = * r {
245- Self :: lookup_bound_region ( debruijn, & br, first_free_index, scopes)
246- } else {
247- r
248- }
249- }
250-
251153 /// Push a new outlives requirement into our output set of
252154 /// constraints.
253155 fn push_outlives (
@@ -314,18 +216,9 @@ where
314216
315217 self . infcx . inner . borrow_mut ( ) . type_variables ( ) . instantiate ( vid, generalized_ty) ;
316218
317- // The generalized values we extract from `canonical_var_values` have
318- // been fully instantiated and hence the set of scopes we have
319- // doesn't matter -- just to be sure, put an empty vector
320- // in there.
321- let old_a_scopes = std:: mem:: take ( pair. vid_scopes ( self ) ) ;
322-
323219 // Relate the generalized kind to the original one.
324220 let result = pair. relate_generalized_ty ( self , generalized_ty) ;
325221
326- // Restore the old scopes now.
327- * pair. vid_scopes ( self ) = old_a_scopes;
328-
329222 debug ! ( "relate_ty_var: complete, result = {:?}" , result) ;
330223 result
331224 }
@@ -379,6 +272,97 @@ where
379272 trace ! ( a = ?a. kind( ) , b = ?b. kind( ) , "opaque type instantiated" ) ;
380273 Ok ( a)
381274 }
275+
276+ #[ instrument( skip( self ) , level = "debug" ) ]
277+ fn instantiate_binder_with_placeholders < T > ( & mut self , binder : ty:: Binder < ' tcx , T > ) -> T
278+ where
279+ T : ty:: TypeFoldable < TyCtxt < ' tcx > > + Copy ,
280+ {
281+ if let Some ( inner) = binder. no_bound_vars ( ) {
282+ return inner;
283+ }
284+
285+ let mut next_region = {
286+ let nll_delegate = & mut self . delegate ;
287+ let mut lazy_universe = None ;
288+
289+ move |br : ty:: BoundRegion | {
290+ // The first time this closure is called, create a
291+ // new universe for the placeholders we will make
292+ // from here out.
293+ let universe = lazy_universe. unwrap_or_else ( || {
294+ let universe = nll_delegate. create_next_universe ( ) ;
295+ lazy_universe = Some ( universe) ;
296+ universe
297+ } ) ;
298+
299+ let placeholder = ty:: PlaceholderRegion { universe, name : br. kind } ;
300+ debug ! ( ?placeholder) ;
301+ let placeholder_reg = nll_delegate. next_placeholder_region ( placeholder) ;
302+ debug ! ( ?placeholder_reg) ;
303+
304+ placeholder_reg
305+ }
306+ } ;
307+
308+ let delegate = FnMutDelegate {
309+ regions : & mut next_region,
310+ types : & mut |_bound_ty : ty:: BoundTy | {
311+ unreachable ! ( "we only replace regions in nll_relate, not types" )
312+ } ,
313+ consts : & mut |_bound_var : ty:: BoundVar , _ty| {
314+ unreachable ! ( "we only replace regions in nll_relate, not consts" )
315+ } ,
316+ } ;
317+
318+ let replaced = self . infcx . tcx . replace_bound_vars_uncached ( binder, delegate) ;
319+ debug ! ( ?replaced) ;
320+
321+ replaced
322+ }
323+
324+ #[ instrument( skip( self ) , level = "debug" ) ]
325+ fn instantiate_binder_with_existentials < T > ( & mut self , binder : ty:: Binder < ' tcx , T > ) -> T
326+ where
327+ T : ty:: TypeFoldable < TyCtxt < ' tcx > > + Copy ,
328+ {
329+ if let Some ( inner) = binder. no_bound_vars ( ) {
330+ return inner;
331+ }
332+
333+ let mut next_region = {
334+ let nll_delegate = & mut self . delegate ;
335+ let mut reg_map = FxHashMap :: default ( ) ;
336+
337+ move |br : ty:: BoundRegion | {
338+ if let Some ( ex_reg_var) = reg_map. get ( & br) {
339+ return * ex_reg_var;
340+ } else {
341+ let ex_reg_var =
342+ nll_delegate. next_existential_region_var ( true , br. kind . get_name ( ) ) ;
343+ debug ! ( ?ex_reg_var) ;
344+ reg_map. insert ( br, ex_reg_var) ;
345+
346+ ex_reg_var
347+ }
348+ }
349+ } ;
350+
351+ let delegate = FnMutDelegate {
352+ regions : & mut next_region,
353+ types : & mut |_bound_ty : ty:: BoundTy | {
354+ unreachable ! ( "we only replace regions in nll_relate, not types" )
355+ } ,
356+ consts : & mut |_bound_var : ty:: BoundVar , _ty| {
357+ unreachable ! ( "we only replace regions in nll_relate, not consts" )
358+ } ,
359+ } ;
360+
361+ let replaced = self . infcx . tcx . replace_bound_vars_uncached ( binder, delegate) ;
362+ debug ! ( ?replaced) ;
363+
364+ replaced
365+ }
382366}
383367
384368/// When we instantiate an inference variable with a value in
@@ -396,14 +380,6 @@ trait VidValuePair<'tcx>: Debug {
396380 /// opposite part of the tuple from the vid).
397381 fn value_ty ( & self ) -> Ty < ' tcx > ;
398382
399- /// Extract the scopes that apply to whichever side of the tuple
400- /// the vid was found on. See the comment where this is called
401- /// for more details on why we want them.
402- fn vid_scopes < ' r , D : TypeRelatingDelegate < ' tcx > > (
403- & self ,
404- relate : & ' r mut TypeRelating < ' _ , ' tcx , D > ,
405- ) -> & ' r mut Vec < BoundRegionScope < ' tcx > > ;
406-
407383 /// Given a generalized type G that should replace the vid, relate
408384 /// G to the value, putting G on whichever side the vid would have
409385 /// appeared.
@@ -425,16 +401,6 @@ impl<'tcx> VidValuePair<'tcx> for (ty::TyVid, Ty<'tcx>) {
425401 self . 1
426402 }
427403
428- fn vid_scopes < ' r , D > (
429- & self ,
430- relate : & ' r mut TypeRelating < ' _ , ' tcx , D > ,
431- ) -> & ' r mut Vec < BoundRegionScope < ' tcx > >
432- where
433- D : TypeRelatingDelegate < ' tcx > ,
434- {
435- & mut relate. a_scopes
436- }
437-
438404 fn relate_generalized_ty < D > (
439405 & self ,
440406 relate : & mut TypeRelating < ' _ , ' tcx , D > ,
@@ -457,16 +423,6 @@ impl<'tcx> VidValuePair<'tcx> for (Ty<'tcx>, ty::TyVid) {
457423 self . 0
458424 }
459425
460- fn vid_scopes < ' r , D > (
461- & self ,
462- relate : & ' r mut TypeRelating < ' _ , ' tcx , D > ,
463- ) -> & ' r mut Vec < BoundRegionScope < ' tcx > >
464- where
465- D : TypeRelatingDelegate < ' tcx > ,
466- {
467- & mut relate. b_scopes
468- }
469-
470426 fn relate_generalized_ty < D > (
471427 & self ,
472428 relate : & mut TypeRelating < ' _ , ' tcx , D > ,
@@ -602,20 +558,14 @@ where
602558 ) -> RelateResult < ' tcx , ty:: Region < ' tcx > > {
603559 debug ! ( ?self . ambient_variance) ;
604560
605- let v_a = self . replace_bound_region ( a, ty:: INNERMOST , & self . a_scopes ) ;
606- let v_b = self . replace_bound_region ( b, ty:: INNERMOST , & self . b_scopes ) ;
607-
608- debug ! ( ?v_a) ;
609- debug ! ( ?v_b) ;
610-
611561 if self . ambient_covariance ( ) {
612562 // Covariant: &'a u8 <: &'b u8. Hence, `'a: 'b`.
613- self . push_outlives ( v_a , v_b , self . ambient_variance_info ) ;
563+ self . push_outlives ( a , b , self . ambient_variance_info ) ;
614564 }
615565
616566 if self . ambient_contravariance ( ) {
617567 // Contravariant: &'b u8 <: &'a u8. Hence, `'b: 'a`.
618- self . push_outlives ( v_b , v_a , self . ambient_variance_info ) ;
568+ self . push_outlives ( b , a , self . ambient_variance_info ) ;
619569 }
620570
621571 Ok ( a)
@@ -689,15 +639,6 @@ where
689639 // instantiation of B (i.e., B instantiated with
690640 // universals).
691641
692- let b_scope = self . create_scope ( b, UniversallyQuantified ( true ) ) ;
693- let a_scope = self . create_scope ( a, UniversallyQuantified ( false ) ) ;
694-
695- debug ! ( ?a_scope, "(existential)" ) ;
696- debug ! ( ?b_scope, "(universal)" ) ;
697-
698- self . b_scopes . push ( b_scope) ;
699- self . a_scopes . push ( a_scope) ;
700-
701642 // Reset the ambient variance to covariant. This is needed
702643 // to correctly handle cases like
703644 //
@@ -718,12 +659,14 @@ where
718659 // subtyping (i.e., `&'b u32 <: &{P} u32`).
719660 let variance = std:: mem:: replace ( & mut self . ambient_variance , ty:: Variance :: Covariant ) ;
720661
721- self . relate ( a. skip_binder ( ) , b. skip_binder ( ) ) ?;
662+ // Note: the order here is important. Create the placeholders first, otherwise
663+ // we assign the wrong universe to the existential!
664+ let b_replaced = self . instantiate_binder_with_placeholders ( b) ;
665+ let a_replaced = self . instantiate_binder_with_existentials ( a) ;
722666
723- self . ambient_variance = variance ;
667+ self . relate ( a_replaced , b_replaced ) ? ;
724668
725- self . b_scopes . pop ( ) . unwrap ( ) ;
726- self . a_scopes . pop ( ) . unwrap ( ) ;
669+ self . ambient_variance = variance;
727670 }
728671
729672 if self . ambient_contravariance ( ) {
@@ -733,26 +676,17 @@ where
733676 // instantiation of B (i.e., B instantiated with
734677 // existentials). Opposite of above.
735678
736- let a_scope = self . create_scope ( a, UniversallyQuantified ( true ) ) ;
737- let b_scope = self . create_scope ( b, UniversallyQuantified ( false ) ) ;
738-
739- debug ! ( ?a_scope, "(universal)" ) ;
740- debug ! ( ?b_scope, "(existential)" ) ;
741-
742- self . a_scopes . push ( a_scope) ;
743- self . b_scopes . push ( b_scope) ;
744-
745679 // Reset ambient variance to contravariance. See the
746680 // covariant case above for an explanation.
747681 let variance =
748682 std:: mem:: replace ( & mut self . ambient_variance , ty:: Variance :: Contravariant ) ;
749683
750- self . relate ( a. skip_binder ( ) , b. skip_binder ( ) ) ?;
684+ let a_replaced = self . instantiate_binder_with_placeholders ( a) ;
685+ let b_replaced = self . instantiate_binder_with_existentials ( b) ;
751686
752- self . ambient_variance = variance ;
687+ self . relate ( a_replaced , b_replaced ) ? ;
753688
754- self . b_scopes . pop ( ) . unwrap ( ) ;
755- self . a_scopes . pop ( ) . unwrap ( ) ;
689+ self . ambient_variance = variance;
756690 }
757691
758692 Ok ( a)
0 commit comments