about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/hir-ty/src/infer/expr.rs10
-rw-r--r--crates/hir-ty/src/tests/regression.rs20
-rw-r--r--crates/ide-diagnostics/src/handlers/type_mismatch.rs19
3 files changed, 45 insertions, 4 deletions
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index 7772fab796c..f3075848430 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -1025,7 +1025,8 @@ impl<'a> InferenceContext<'a> {
                 )
             }
         };
-
+        // Try to evaluate unevaluated constant, and insert variable if is not possible.
+        let len = self.table.insert_const_vars_shallow(len);
         TyKind::Array(elem_ty, len).intern(Interner)
     }
 
@@ -1681,9 +1682,10 @@ impl<'a> InferenceContext<'a> {
                 } else {
                     param_ty
                 };
-                if !coercion_target.is_unknown()
-                    && self.coerce(Some(arg), &ty, &coercion_target).is_err()
-                {
+                // The function signature may contain some unknown types, so we need to insert
+                // type vars here to avoid type mismatch false positive.
+                let coercion_target = self.insert_type_vars(coercion_target);
+                if self.coerce(Some(arg), &ty, &coercion_target).is_err() {
                     self.result.type_mismatches.insert(
                         arg.into(),
                         TypeMismatch { expected: coercion_target, actual: ty.clone() },
diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs
index 259f43e7e20..1fdeddede09 100644
--- a/crates/hir-ty/src/tests/regression.rs
+++ b/crates/hir-ty/src/tests/regression.rs
@@ -1891,4 +1891,24 @@ fn main() {
 }
         "#,
     );
+    check_no_mismatches(
+        r#"
+pub const N: usize = 2 + 2;
+
+fn f(t: [u8; N]) {}
+
+fn main() {
+    let a = [1, 2, 3, 4];
+    f(a);
+    let b = [1; 4];
+    let c: [u8; N] = b;
+    let d = [1; N];
+    let e: [u8; N] = d;
+    let f = [1; N];
+    let g = match f {
+        [a, b, c, d] => a + b + c + d,
+    };
+}
+        "#,
+    );
 }
diff --git a/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/crates/ide-diagnostics/src/handlers/type_mismatch.rs
index cc282bf9348..c28f98d8333 100644
--- a/crates/ide-diagnostics/src/handlers/type_mismatch.rs
+++ b/crates/ide-diagnostics/src/handlers/type_mismatch.rs
@@ -645,6 +645,25 @@ fn h() {
     }
 
     #[test]
+    fn unknown_type_in_function_signature() {
+        check_diagnostics(
+            r#"
+struct X<T>(T);
+
+fn foo(x: X<Unknown>) {}
+fn test1() {
+    // Unknown might be `i32`, so we should not emit type mismatch here.
+    foo(X(42));
+}
+fn test2() {
+    foo(42);
+      //^^ error: expected X<{unknown}>, found i32
+}
+"#,
+        );
+    }
+
+    #[test]
     fn evaluate_const_generics_in_types() {
         check_diagnostics(
             r#"