Coerce two FnDefs to fn pointers even if they are the same, if they are subtypes

That's because they can be the same function but still different substs, which mandates them to coerce to fn pointers in order to unify.
This commit is contained in:
Chayim Refael Friedman 2024-12-07 19:16:00 +02:00
parent 39fd171808
commit a9e015f8ee
2 changed files with 21 additions and 1 deletions

View file

@ -125,7 +125,11 @@ impl CoerceMany {
// pointers to have a chance at getting a match. See
// https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916
let sig = match (self.merged_ty().kind(Interner), expr_ty.kind(Interner)) {
(TyKind::FnDef(x, _), TyKind::FnDef(y, _)) if x == y => None,
(TyKind::FnDef(x, _), TyKind::FnDef(y, _))
if x == y && ctx.table.unify(&self.merged_ty(), &expr_ty) =>
{
None
}
(TyKind::Closure(x, _), TyKind::Closure(y, _)) if x == y => None,
(TyKind::FnDef(..) | TyKind::Closure(..), TyKind::FnDef(..) | TyKind::Closure(..)) => {
// FIXME: we're ignoring safety here. To be more correct, if we have one FnDef and one Closure,

View file

@ -942,3 +942,19 @@ fn main() {
"#,
)
}
#[test]
fn regression_18626() {
check_no_mismatches(
r#"
fn f() {
trait T {
fn f() {}
}
impl T for i32 {}
impl T for u32 {}
&[i32::f, u32::f] as &[fn()];
}
"#,
);
}