Repository: intellij-rust/intellij-rust
Issue: ACT: Explicit types are not generated correctly for ref declarations

<!--
Hello and thank you for the issue!
If you would like to report a bug, we have added some points below that you can fill out.
Feel free to remove all the irrelevant text to request a new feature.
-->

## Environment

* **IntelliJ Rust plugin version:** 0.2.118.2171-193
* **Rust toolchain version:** cargo 1.44.0-nightly (7019b3ed3 2020-03-17)
* **IDE name and version:** IDEA 2019.3.4
* **Operating system:** Windows 10

## Problem description

```rust
fn main() {
    let ref num = 1;
    // Use the `Specify type explicitly`
    //     let ref num: &i32 = 1;
    // Error:
    // 2 |     let ref num: &i32 = 1;
    //   |                         ^ expected `&i32`, found integer
}
```

## Steps to reproduce

1. Use the following code:

```rust
fn main() {
    let ref num/*caret*/ = 1;
}
```

2. Use the `Specify type explicitly`
3. Run `cargo check`

<!--
Please include as much of your codebase as needed to reproduce the error.
If the relevant files are large, please provide a link to a public repository or a [Gist](https://gist.github.com/).
-->


Changed files:
src/main/kotlin/org/rust/ide/intentions/SpecifyTypeExplicitlyIntention.kt, src/test/kotlin/org/rust/ide/intentions/SpecifyTypeExplicitlyIntentionTest.kt

diff --git a/src/main/kotlin/org/rust/ide/intentions/SpecifyTypeExplicitlyIntention.kt b/src/main/kotlin/org/rust/ide/intentions/SpecifyTypeExplicitlyIntention.kt
index 71427d9e4..efe500ab4 100644
--- a/src/main/kotlin/org/rust/ide/intentions/SpecifyTypeExplicitlyIntention.kt
+++ b/src/main/kotlin/org/rust/ide/intentions/SpecifyTypeExplicitlyIntention.kt
@@ -11,18 +11,18 @@ import com.intellij.psi.PsiElement
 import org.rust.ide.inspections.import.RsImportHelper.importTypeReferencesFromTy
 import org.rust.ide.presentation.insertionSafeTextWithAliases
 import org.rust.lang.core.psi.RsLetDecl
+import org.rust.lang.core.psi.RsPatIdent
 import org.rust.lang.core.psi.RsPsiFactory
+import org.rust.lang.core.psi.ext.RsBindingModeKind.BindByReference
 import org.rust.lang.core.psi.ext.ancestorStrict
+import org.rust.lang.core.psi.ext.kind
 import org.rust.lang.core.psi.ext.startOffset
 import org.rust.lang.core.types.consts.CtInferVar
 import org.rust.lang.core.types.consts.CtUnevaluated
 import org.rust.lang.core.types.consts.CtUnknown
 import org.rust.lang.core.types.infer.containsConstOfClass
 import org.rust.lang.core.types.infer.containsTyOfClass
-import org.rust.lang.core.types.ty.Ty
-import org.rust.lang.core.types.ty.TyAnon
-import org.rust.lang.core.types.ty.TyInfer
-import org.rust.lang.core.types.ty.TyUnknown
+import org.rust.lang.core.types.ty.*
 import org.rust.lang.core.types.type
 
 
@@ -37,11 +37,19 @@ class SpecifyTypeExplicitlyIntention : RsElementBaseIntentionAction<SpecifyTypeE
         val initializer = letDecl.expr
         if (initializer != null && element.startOffset >= initializer.startOffset - 1) return null
         val pat = letDecl.pat ?: return null
-        val type = pat.type
-        if (type.containsTyOfClass(TyUnknown::class.java, TyInfer::class.java, TyAnon::class.java)
-            || type.containsConstOfClass(CtUnknown::class.java, CtInferVar::class.java, CtUnevaluated::class.java)) {
+        val patType = pat.type
+        if (patType.containsTyOfClass(TyUnknown::class.java, TyInfer::class.java, TyAnon::class.java)
+            || patType.containsConstOfClass(CtUnknown::class.java, CtInferVar::class.java, CtUnevaluated::class.java)) {
             return null
         }
+
+        // let ref x = 1; // `i32` should be inserted instead of `&i32`
+        val type = if (pat is RsPatIdent && pat.patBinding.kind is BindByReference && patType is TyReference) {
+            patType.referenced
+        } else {
+            patType
+        }
+
         return Context(type, letDecl)
     }
 
diff --git a/src/test/kotlin/org/rust/ide/intentions/SpecifyTypeExplicitlyIntentionTest.kt b/src/test/kotlin/org/rust/ide/intentions/SpecifyTypeExplicitlyIntentionTest.kt
index a73a5ed07..cca2976b8 100644
--- a/src/test/kotlin/org/rust/ide/intentions/SpecifyTypeExplicitlyIntentionTest.kt
+++ b/src/test/kotlin/org/rust/ide/intentions/SpecifyTypeExplicitlyIntentionTest.kt
@@ -164,4 +164,14 @@ class SpecifyTypeExplicitlyIntentionTest : RsIntentionTestBase(SpecifyTypeExplic
             }
             fn main() { let var: HashMap<i32, i32, RandomState> = foo(); }
     """)
+
+    fun `test ref pat`() = doAvailableTest(
+        """ fn main() { let ref var/*caret*/ = 42; } """,
+        """ fn main() { let ref var: i32 = 42; } """
+    )
+
+    fun `test ref mut pat`() = doAvailableTest(
+        """ fn main() { let ref mut var/*caret*/ = 42; } """,
+        """ fn main() { let ref mut var: i32 = 42; } """
+    )
 }