diff --git a/crates/hir-ty/src/infer/coerce.rs b/crates/hir-ty/src/infer/coerce.rs index 366c3cb0f177..2fe90a8a9243 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 273571901ad5..7992f1feeeb1 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()]; +} + "#, + ); +}