2020use rustc_middle:: traits:: solve:: Goal ;
2121use rustc_middle:: ty:: relate:: combine:: { super_combine_consts, super_combine_tys} ;
2222use rustc_middle:: ty:: relate:: { Relate , RelateResult , TypeRelation } ;
23- use rustc_middle:: ty:: { self , Ty , TyCtxt , TyVar , TypeVisitableExt } ;
23+ use rustc_middle:: ty:: { self , Ty , TyCtxt , TyVar } ;
2424use rustc_span:: Span ;
25- use tracing:: { debug , instrument} ;
25+ use tracing:: instrument;
2626
2727use super :: StructurallyRelateAliases ;
2828use super :: combine:: PredicateEmittingRelation ;
29- use crate :: infer:: { DefineOpaqueTypes , InferCtxt , SubregionOrigin , TypeTrace } ;
29+ use crate :: infer:: {
30+ BoundRegionConversionTime , DefineOpaqueTypes , InferCtxt , SubregionOrigin , TypeTrace ,
31+ } ;
3032use crate :: traits:: { Obligation , PredicateObligations } ;
3133
3234#[ derive( Clone , Copy ) ]
@@ -195,6 +197,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for LatticeOp<'_, 'tcx> {
195197 super_combine_consts ( self . infcx , self , a, b)
196198 }
197199
200+ #[ instrument( level = "trace" , skip( self ) ) ]
198201 fn binders < T > (
199202 & mut self ,
200203 a : ty:: Binder < ' tcx , T > ,
@@ -208,16 +211,35 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for LatticeOp<'_, 'tcx> {
208211 return Ok ( a) ;
209212 }
210213
211- debug ! ( "binders(a={:?}, b={:?})" , a, b) ;
212- if a. skip_binder ( ) . has_escaping_bound_vars ( ) || b. skip_binder ( ) . has_escaping_bound_vars ( ) {
214+ let instantiate_with_infer = |binder| {
215+ let span = self . span ( ) ;
216+ let brct = BoundRegionConversionTime :: HigherRankedType ;
217+ self . infcx . instantiate_binder_with_fresh_vars ( span, brct, binder)
218+ } ;
219+ let r = match ( a. no_bound_vars ( ) , b. no_bound_vars ( ) ) {
213220 // When higher-ranked types are involved, computing the GLB/LUB is
214221 // very challenging, switch to invariance. This is obviously
215222 // overly conservative but works ok in practice.
216- self . relate_with_variance ( ty:: Invariant , ty:: VarianceDiagInfo :: default ( ) , a, b) ?;
217- Ok ( a)
218- } else {
219- Ok ( ty:: Binder :: dummy ( self . relate ( a. skip_binder ( ) , b. skip_binder ( ) ) ?) )
220- }
223+ ( None , None ) => {
224+ self . relate_with_variance ( ty:: Invariant , ty:: VarianceDiagInfo :: default ( ) , a, b) ?;
225+ return Ok ( a) ;
226+ }
227+
228+ // If we only have one type with bound vars then we convert
229+ // it to a non higher-ranked signature, This should always
230+ // be correct assuming we do not support subtyping of the form:
231+ // `fn(&'smallest ()) <: for<'a> fn(&'a ())`
232+ // but I don't think we currently do so or intend to start doing so.
233+ //
234+ // This is a bit of a special case but it was necessary for backwards
235+ // compatibility when starting to properly leak checking in coercions.
236+ ( Some ( a) , None ) => self . relate ( a, instantiate_with_infer ( b) ) ?,
237+ ( None , Some ( b) ) => self . relate ( instantiate_with_infer ( a) , b) ?,
238+
239+ ( Some ( a) , Some ( b) ) => self . relate ( a, b) ?,
240+ } ;
241+
242+ Ok ( ty:: Binder :: dummy ( r) )
221243 }
222244}
223245
0 commit comments