Unnamed repository; edit this file 'description' to name the repository.
Coerce two `FnDef`s 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.
| -rw-r--r-- | crates/hir-ty/src/infer/coerce.rs | 6 | ||||
| -rw-r--r-- | crates/hir-ty/src/tests/coercion.rs | 16 |
2 files changed, 21 insertions, 1 deletions
diff --git a/crates/hir-ty/src/infer/coerce.rs b/crates/hir-ty/src/infer/coerce.rs index 366c3cb0f1..2fe90a8a92 100644 --- a/crates/hir-ty/src/infer/coerce.rs +++ b/crates/hir-ty/src/infer/coerce.rs @@ -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, diff --git a/crates/hir-ty/src/tests/coercion.rs b/crates/hir-ty/src/tests/coercion.rs index 273571901a..7992f1feee 100644 --- a/crates/hir-ty/src/tests/coercion.rs +++ b/crates/hir-ty/src/tests/coercion.rs @@ -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()]; +} + "#, + ); +} |