@@ -26,7 +26,9 @@ use tracing::{debug, 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 ) ]
@@ -209,15 +211,38 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for LatticeOp<'_, 'tcx> {
209211 }
210212
211213 debug ! ( "binders(a={:?}, b={:?})" , a, b) ;
212- if a. skip_binder ( ) . has_escaping_bound_vars ( ) || b. skip_binder ( ) . has_escaping_bound_vars ( ) {
214+
215+ let instantiate_with_infer = |binder| {
216+ self . infcx . instantiate_binder_with_fresh_vars (
217+ self . span ( ) ,
218+ BoundRegionConversionTime :: HigherRankedType ,
219+ binder,
220+ )
221+ } ;
222+ let r = match ( a. no_bound_vars ( ) , b. no_bound_vars ( ) ) {
213223 // When higher-ranked types are involved, computing the GLB/LUB is
214224 // very challenging, switch to invariance. This is obviously
215225 // 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- }
226+ ( None , None ) => {
227+ self . relate_with_variance ( ty:: Invariant , ty:: VarianceDiagInfo :: default ( ) , a, b) ?;
228+ return Ok ( a) ;
229+ }
230+
231+ // If we only have one type with bound vars then we convert
232+ // it to a non higher-ranked signature, This should always
233+ // be correct assuming we do not support subtyping of the form:
234+ // `fn(&'smallest ()) <: for<'a> fn(&'a ())`
235+ // but I don't think we currently do so or intend to start doing so.
236+ //
237+ // This is a bit of a special case but it was necessary for backwards
238+ // compatibility when starting to properly leak checking in coercions.
239+ ( Some ( a) , None ) => self . relate ( a, instantiate_with_infer ( b) ) ?,
240+ ( None , Some ( b) ) => self . relate ( instantiate_with_infer ( a) , b) ?,
241+
242+ ( Some ( a) , Some ( b) ) => self . relate ( a, b) ?,
243+ } ;
244+
245+ Ok ( ty:: Binder :: dummy ( r) )
221246 }
222247}
223248
0 commit comments