Skip to content

Commit 0dd23cc

Browse files
committed
Skip HR function pointers coercion fallback when neither side is HR
1 parent 309dce1 commit 0dd23cc

1 file changed

Lines changed: 22 additions & 4 deletions

File tree

compiler/rustc_hir_typeck/src/coercion.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)