about summary refs log tree commit diff
diff options
context:
space:
mode:
authorChayim Refael Friedman <chayimfr@gmail.com>2024-12-07 19:16:00 +0200
committerChayim Refael Friedman <chayimfr@gmail.com>2024-12-07 19:16:00 +0200
commit19077860388fa32f3747632ad87b51d79a9ef9dc (patch)
treea04e542c91d6a3c2744afd55dec1d52051c34d4e
parent39aab9839c617780d65222eca48739f15ada0292 (diff)
downloadrust-19077860388fa32f3747632ad87b51d79a9ef9dc.tar.gz
rust-19077860388fa32f3747632ad87b51d79a9ef9dc.zip
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--src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs16
2 files changed, 21 insertions, 1 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs
index 366c3cb0f17..2fe90a8a924 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs
index 273571901ad..7992f1feeeb 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs
+++ b/src/tools/rust-analyzer/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()];
+}
+    "#,
+    );
+}