@@ -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,14 +211,31 @@ 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 ( ) {
213- // When higher-ranked types are involved, computing the GLB/LUB is
214- // very challenging, switch to invariance. This is obviously
215- // 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 ( ) ) ?) )
214+ match ( a. no_bound_vars ( ) . ok_or ( a) , b. no_bound_vars ( ) . ok_or ( b) ) {
215+ ( Err ( a) , Err ( b) ) => {
216+ // When higher-ranked types are involved, computing the GLB/LUB is
217+ // very challenging, switch to invariance. This is obviously
218+ // overly conservative but works ok in practice.
219+ self . relate_with_variance ( ty:: Invariant , ty:: VarianceDiagInfo :: default ( ) , a, b) ?;
220+ Ok ( a)
221+ }
222+ ( Ok ( non_hr) , Err ( hr) ) | ( Err ( hr) , Ok ( non_hr) ) => {
223+ // If we only have one type with bound vars then we convert
224+ // it to a non higher-ranked signature, This should always
225+ // be correct assuming we do not support subtyping of the form:
226+ // `fn(&'smallest ()) <: for<'a> fn(&'a ())`
227+ // but I don't think we currently do so or intend to start doing so.
228+ //
229+ // This is a bit of a special case but it was necessary for backwards
230+ // compatibility when starting to properly leak checking in coercions.
231+ let non_hr_2 = self . infcx . instantiate_binder_with_fresh_vars (
232+ self . span ( ) ,
233+ BoundRegionConversionTime :: HigherRankedType ,
234+ hr,
235+ ) ;
236+ Ok ( ty:: Binder :: dummy ( self . relate ( non_hr, non_hr_2) ?) )
237+ }
238+ ( Ok ( a) , Ok ( b) ) => Ok ( ty:: Binder :: dummy ( self . relate ( a, b) ?) ) ,
220239 }
221240 }
222241}
0 commit comments