From d5a43d1f859597dbdb566a717e7278acb8b2c767 Mon Sep 17 00:00:00 2001
From: Lukas Wirth <lukastw97@gmail.com>
Date: Sat, 10 Jul 2021 18:19:23 +0200
Subject: [PATCH 1/2] Resolve type adjustments

---
 crates/hir_ty/src/infer.rs | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index b1c0432273d..154c44afa42 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -407,6 +407,12 @@ impl<'a> InferenceContext<'a> {
         for (_, subst) in result.method_resolutions.values_mut() {
             *subst = self.table.resolve_completely(subst.clone());
         }
+        for adjustment in result.expr_adjustments.values_mut().flatten() {
+            adjustment.target = self.table.resolve_completely(adjustment.target.clone());
+        }
+        for adjustment in result.pat_adjustments.values_mut().flatten() {
+            adjustment.target = self.table.resolve_completely(adjustment.target.clone());
+        }
         result
     }
 

From 576e3a4e122ac7089d6e209a86cbf825e927908b Mon Sep 17 00:00:00 2001
From: Lukas Wirth <lukastw97@gmail.com>
Date: Sat, 10 Jul 2021 18:19:46 +0200
Subject: [PATCH 2/2] `add_explicit_type` respects coercions

---
 crates/hir/src/semantics.rs                   |  8 ++++++++
 crates/hir/src/source_analyzer.rs             | 15 ++++++++++++++
 crates/hir_ty/src/tests/coercion.rs           |  2 +-
 .../src/handlers/add_explicit_type.rs         | 20 ++++++++++++++++++-
 4 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 43162797e3c..984021d59ec 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -216,6 +216,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
         self.imp.type_of_expr(expr)
     }
 
+    pub fn type_of_expr_with_coercion(&self, expr: &ast::Expr) -> Option<Type> {
+        self.imp.type_of_expr_with_coercion(expr)
+    }
+
     pub fn type_of_pat(&self, pat: &ast::Pat) -> Option<Type> {
         self.imp.type_of_pat(pat)
     }
@@ -560,6 +564,10 @@ impl<'db> SemanticsImpl<'db> {
         self.analyze(expr.syntax()).type_of_expr(self.db, expr)
     }
 
+    fn type_of_expr_with_coercion(&self, expr: &ast::Expr) -> Option<Type> {
+        self.analyze(expr.syntax()).type_of_expr_with_coercion(self.db, expr)
+    }
+
     fn type_of_pat(&self, pat: &ast::Pat) -> Option<Type> {
         self.analyze(pat.syntax()).type_of_pat(self.db, pat)
     }
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index c9744d81d22..474fb3fe30a 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -122,6 +122,21 @@ impl SourceAnalyzer {
         Type::new_with_resolver(db, &self.resolver, ty)
     }
 
+    pub(crate) fn type_of_expr_with_coercion(
+        &self,
+        db: &dyn HirDatabase,
+        expr: &ast::Expr,
+    ) -> Option<Type> {
+        let expr_id = self.expr_id(db, expr)?;
+        let infer = self.infer.as_ref()?;
+        let ty = infer
+            .expr_adjustments
+            .get(&expr_id)
+            .and_then(|adjusts| adjusts.last().map(|adjust| &adjust.target))
+            .unwrap_or_else(|| &infer[expr_id]);
+        Type::new_with_resolver(db, &self.resolver, ty.clone())
+    }
+
     pub(crate) fn type_of_pat(&self, db: &dyn HirDatabase, pat: &ast::Pat) -> Option<Type> {
         let pat_id = self.pat_id(pat)?;
         let ty = self.infer.as_ref()?[pat_id].clone();
diff --git a/crates/hir_ty/src/tests/coercion.rs b/crates/hir_ty/src/tests/coercion.rs
index 1e30e2e8c1d..aecc482cfdc 100644
--- a/crates/hir_ty/src/tests/coercion.rs
+++ b/crates/hir_ty/src/tests/coercion.rs
@@ -46,7 +46,7 @@ fn test2() {
 
 #[test]
 fn let_stmt_coerce() {
-    check_no_mismatches(
+    check(
         r"
 //- minicore: coerce_unsized
 fn test() {
diff --git a/crates/ide_assists/src/handlers/add_explicit_type.rs b/crates/ide_assists/src/handlers/add_explicit_type.rs
index b7617ca3da8..b0e8fb6559f 100644
--- a/crates/ide_assists/src/handlers/add_explicit_type.rs
+++ b/crates/ide_assists/src/handlers/add_explicit_type.rs
@@ -55,7 +55,7 @@ pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext) -> Optio
     }
 
     // Infer type
-    let ty = ctx.sema.type_of_expr(&expr)?;
+    let ty = ctx.sema.type_of_expr_with_coercion(&expr)?;
     if ty.contains_unknown() || ty.is_closure() {
         cov_mark::hit!(add_explicit_type_not_applicable_if_ty_not_inferred);
         return None;
@@ -258,6 +258,24 @@ fn main() {
 fn main() {
     let test @ (): () = ();
 }
+"#,
+        );
+    }
+
+    #[test]
+    fn add_explicit_type_inserts_coercions() {
+        check_assist(
+            add_explicit_type,
+            r#"
+//- minicore: coerce_unsized
+fn f() {
+    let $0x: *const [_] = &[3];
+}
+"#,
+            r#"
+fn f() {
+    let x: *const [i32] = &[3];
+}
 "#,
         );
     }