Repository: rust-lang/rust-analyzer (rust)

Issue:
[BUG] Const generics broken when inside struct
### Versions:
**rust-analyzer version**: 2023-05-15 & [Nightly](https://github.com/rust-lang/rust-analyzer/commit/0a806fe7ad28efa2de22ed3c9d3233cd1ed08dd1)

**rustc version**: 1.69.0

**relevant settings**: https://github.com/utkarshgupta137/nvim-lazy/blob/main/lua/lvim/lsp/settings/rust_analyzer.lua

### Minimal reproduction:
```rust
pub const ONE: usize = 1;

pub struct Inner<const P: usize>();

pub struct Outer {
    pub inner: Inner<ONE>,
}

fn main() {
    _ = Outer {
        inner: Inner::<1>(), // Error: expected Inner<ONE>, found Inner<1> | rust-analyzer (type-mismatch) [11, 16]
    };
}
```

### Diagnosis:
The bug doesn't exist in the 2023-05-08 release.
This PR included in the 2023-05-15 release seems relevant: https://github.com/rust-lang/rust-analyzer/pull/14727

Pull request:
Evaluate `UnevaluatedConst` in unify
fix #14844 

Patch:
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index b800c2e32a..7772fab796 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -575,6 +575,9 @@ impl<'a> InferenceContext<'a> {
                     let field_ty = field_def.map_or(self.err_ty(), |it| {
                         field_types[it.local_id].clone().substitute(Interner, &substs)
                     });
+                    // Field type might have some unknown types
+                    // FIXME: we may want to emit a single type variable for all instance of type fields?
+                    let field_ty = self.insert_type_vars(field_ty);
                     self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty));
                 }
                 if let Some(expr) = spread {
diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs
index 21b962a48f..38eae475b5 100644
--- a/crates/hir-ty/src/infer/unify.rs
+++ b/crates/hir-ty/src/infer/unify.rs
@@ -781,8 +781,16 @@ impl<'a> InferenceTable<'a> {
     pub(super) fn insert_const_vars_shallow(&mut self, c: Const) -> Const {
         let data = c.data(Interner);
         match &data.value {
-            ConstValue::Concrete(cc) => match cc.interned {
+            ConstValue::Concrete(cc) => match &cc.interned {
                 crate::ConstScalar::Unknown => self.new_const_var(data.ty.clone()),
+                // try to evaluate unevaluated const. Replace with new var if const eval failed.
+                crate::ConstScalar::UnevaluatedConst(id, subst) => {
+                    if let Ok(eval) = self.db.const_eval(*id, subst.clone()) {
+                        eval
+                    } else {
+                        self.new_const_var(data.ty.clone())
+                    }
+                }
                 _ => c,
             },
             _ => c,
diff --git a/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/crates/ide-diagnostics/src/handlers/type_mismatch.rs
index a5359741ac..cc282bf934 100644
--- a/crates/ide-diagnostics/src/handlers/type_mismatch.rs
+++ b/crates/ide-diagnostics/src/handlers/type_mismatch.rs
@@ -644,6 +644,28 @@ fn h() {
         );
     }
 
+    #[test]
+    fn evaluate_const_generics_in_types() {
+        check_diagnostics(
+            r#"
+pub const ONE: usize = 1;
+
+pub struct Inner<const P: usize>();
+
+pub struct Outer {
+    pub inner: Inner<ONE>,
+}
+
+fn main() {
+    _ = Outer {
+        inner: Inner::<2>(),
+             //^^^^^^^^^^^^ error: expected Inner<1>, found Inner<2>
+    };
+}
+"#,
+        );
+    }
+
     #[test]
     fn type_mismatch_pat_smoke_test() {
         check_diagnostics(


Test patch:
diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs
index 9f5f1ea325..259f43e7e2 100644
--- a/crates/hir-ty/src/tests/regression.rs
+++ b/crates/hir-ty/src/tests/regression.rs
@@ -1837,3 +1837,58 @@ fn foo() {
 }",
     );
 }
+
+#[test]
+fn regression_14844() {
+    check_no_mismatches(
+        r#"
+pub type Ty = Unknown;
+
+pub struct Inner<T>();
+
+pub struct Outer {
+    pub inner: Inner<Ty>,
+}
+
+fn main() {
+    _ = Outer {
+        inner: Inner::<i32>(),
+    };
+}
+        "#,
+    );
+    check_no_mismatches(
+        r#"
+pub const ONE: usize = 1;
+
+pub struct Inner<const P: usize>();
+
+pub struct Outer {
+    pub inner: Inner<ONE>,
+}
+
+fn main() {
+    _ = Outer {
+        inner: Inner::<1>(),
+    };
+}
+        "#,
+    );
+    check_no_mismatches(
+        r#"
+pub const ONE: usize = unknown();
+
+pub struct Inner<const P: usize>();
+
+pub struct Outer {
+    pub inner: Inner<ONE>,
+}
+
+fn main() {
+    _ = Outer {
+        inner: Inner::<1>(),
+    };
+}
+        "#,
+    );
+}