@@ -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)
@@ -1075,7 +1083,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
10751083
10761084 match self . unify_and ( a, b, [ ] , adjust. clone ( ) , ForceLeakCheck :: Yes ) {
10771085 ok @ Ok ( _) => ok,
1078- Err ( _) => {
1086+ Err ( _) if self . coercion_is_higher_ranked ( a_sig , b ) => {
10791087 let ty:: FnPtr ( b_sig_tys, b_hdr) = b. kind ( ) else {
10801088 span_bug ! (
10811089 self . cause. span,
@@ -1125,11 +1133,15 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
11251133 )
11261134 } )
11271135 }
1136+ Err ( err) => Err ( err) ,
11281137 }
11291138 }
11301139 ty:: FnPtr ( _, _) => match self . unify ( a, b, ForceLeakCheck :: Yes ) {
11311140 ok @ Ok ( _) => ok,
1132- Err ( _) => self . unify_hr_fn_ptr ( a_sig, b, Adjust :: Subtype ) ,
1141+ Err ( _) if self . coercion_is_higher_ranked ( a_sig, b) => {
1142+ self . unify_hr_fn_ptr ( a_sig, b, Adjust :: Subtype )
1143+ }
1144+ Err ( err) => Err ( err) ,
11331145 } ,
11341146 _ => self . unify ( a, b, ForceLeakCheck :: Yes ) ,
11351147 }
@@ -1151,7 +1163,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
11511163 let adjust = Adjust :: Pointer ( PointerCoercion :: ReifyFnPointer ( b_hdr. safety ( ) ) ) ;
11521164 let infer = match self . unify_and ( a, b, [ ] , adjust. clone ( ) , ForceLeakCheck :: Yes ) {
11531165 Ok ( infer) => infer,
1154- Err ( _) => self . unify_hr_fn_ptr ( a_sig, b, adjust) ?,
1166+ Err ( _) if self . coercion_is_higher_ranked ( a_sig, b) => {
1167+ self . unify_hr_fn_ptr ( a_sig, b, adjust) ?
1168+ }
1169+ Err ( err) => return Err ( err) ,
11551170 } ;
11561171 obligations. extend ( infer. obligations ) ;
11571172 Ok ( InferOk { value : infer. value , obligations } )
@@ -1177,7 +1192,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
11771192 let adjust = Adjust :: Pointer ( PointerCoercion :: ClosureFnPointer ( safety) ) ;
11781193 match self . unify_and ( pointer_ty, b, [ ] , adjust. clone ( ) , ForceLeakCheck :: No ) {
11791194 ok @ Ok ( _) => ok,
1180- Err ( _) => self . unify_hr_fn_ptr ( closure_sig, b, adjust) ,
1195+ Err ( _) if self . coercion_is_higher_ranked ( closure_sig, b) => {
1196+ self . unify_hr_fn_ptr ( closure_sig, b, adjust)
1197+ }
1198+ Err ( err) => Err ( err) ,
11811199 }
11821200 }
11831201 _ => self . unify ( a, b, ForceLeakCheck :: No ) ,
0 commit comments