@@ -252,6 +252,14 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
252252 } )
253253 }
254254
255+ /// Whether a fn-pointer coercion involves a higher-ranked binder (source or
256+ /// target). If neither is higher-ranked, the `unify_hr_fn_ptr` fallback is a
257+ /// no-op re-relate of the same types.
258+ fn coercion_is_higher_ranked ( & self , a_sig : ty:: PolyFnSig < ' tcx > , b : Ty < ' tcx > ) -> bool {
259+ a_sig. has_bound_regions ( )
260+ || matches ! ( * b. kind( ) , ty:: FnPtr ( tys, hdr) if tys. with( hdr) . has_bound_regions( ) )
261+ }
262+
255263 /// Unify two types (using sub or lub).
256264 fn unify ( & self , a : Ty < ' tcx > , b : Ty < ' tcx > , leak_check : ForceLeakCheck ) -> CoerceResult < ' tcx > {
257265 self . unify_raw ( a, b, leak_check)
@@ -1088,7 +1096,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
10881096
10891097 match self . unify_and ( a, b, [ ] , adjust. clone ( ) , ForceLeakCheck :: Yes ) {
10901098 ok @ Ok ( _) => ok,
1091- Err ( _) => {
1099+ Err ( _) if self . coercion_is_higher_ranked ( a_sig , b ) => {
10921100 let ty:: FnPtr ( b_sig_tys, b_hdr) = b. kind ( ) else {
10931101 span_bug ! (
10941102 self . cause. span,
@@ -1138,11 +1146,15 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
11381146 )
11391147 } )
11401148 }
1149+ Err ( err) => Err ( err) ,
11411150 }
11421151 }
11431152 ty:: FnPtr ( _, _) => match self . unify ( a, b, ForceLeakCheck :: Yes ) {
11441153 ok @ Ok ( _) => ok,
1145- Err ( _) => self . unify_hr_fn_ptr ( a_sig, b, Adjust :: Subtype ) ,
1154+ Err ( _) if self . coercion_is_higher_ranked ( a_sig, b) => {
1155+ self . unify_hr_fn_ptr ( a_sig, b, Adjust :: Subtype )
1156+ }
1157+ Err ( err) => Err ( err) ,
11461158 } ,
11471159 _ => self . unify ( a, b, ForceLeakCheck :: Yes ) ,
11481160 }
@@ -1164,7 +1176,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
11641176 let adjust = Adjust :: Pointer ( PointerCoercion :: ReifyFnPointer ( b_hdr. safety ( ) ) ) ;
11651177 let infer = match self . unify_and ( a, b, [ ] , adjust. clone ( ) , ForceLeakCheck :: Yes ) {
11661178 Ok ( infer) => infer,
1167- Err ( _) => self . unify_hr_fn_ptr ( a_sig, b, adjust) ?,
1179+ Err ( _) if self . coercion_is_higher_ranked ( a_sig, b) => {
1180+ self . unify_hr_fn_ptr ( a_sig, b, adjust) ?
1181+ }
1182+ Err ( err) => return Err ( err) ,
11681183 } ;
11691184 obligations. extend ( infer. obligations ) ;
11701185 Ok ( InferOk { value : infer. value , obligations } )
@@ -1190,7 +1205,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
11901205 let adjust = Adjust :: Pointer ( PointerCoercion :: ClosureFnPointer ( safety) ) ;
11911206 match self . unify_and ( pointer_ty, b, [ ] , adjust. clone ( ) , ForceLeakCheck :: No ) {
11921207 ok @ Ok ( _) => ok,
1193- Err ( _) => self . unify_hr_fn_ptr ( closure_sig, b, adjust) ,
1208+ Err ( _) if self . coercion_is_higher_ranked ( closure_sig, b) => {
1209+ self . unify_hr_fn_ptr ( closure_sig, b, adjust)
1210+ }
1211+ Err ( err) => Err ( err) ,
11941212 }
11951213 }
11961214 _ => self . unify ( a, b, ForceLeakCheck :: No ) ,
0 commit comments