Repository: intellij-rust/intellij-rust
Issue: Introducing variable in incorrect scope

<!--
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.4.153.4056-212
* **Rust toolchain version:** 1.54.0 (a178d0322 2021-07-26) x86_64-pc-windows-msvc
* **IDE name and version:** CLion 2021.2.1 (CL-212.5080.54)
* **Operating system:** Windows 10 10.0
* **Macro expansion engine:** new
* **Name resolution engine:** new

## Problem description

When introducing a variable in lambda without braces, the variable gets created outside the lambda.

## Steps to reproduce

```rust
Ok(String::new()).and_then(|value| match value.as_str() {
    "foo" => foo(),
    _ => bar(),
});
```

When introducing a new variable from `value.as_str()`, the resulting code should look like:

```rust
Ok(String::new()).and_then(|value| {
    let v = value.as_str();
    match v {
        "foo" => foo(),
        _ => bar(),
    }
});
```

Instead, the code looks like this:

```rust
let v = value.as_str();
Ok(String::new()).and_then(|value| match v {
    "foo" => foo(),
    _ => bar(),
});
```

<!--
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/refactoring/introduceVariable/impl.kt, src/test/kotlin/org/rust/ide/refactoring/RsIntroduceVariableHandlerTest.kt

diff --git a/src/main/kotlin/org/rust/ide/refactoring/introduceVariable/impl.kt b/src/main/kotlin/org/rust/ide/refactoring/introduceVariable/impl.kt
index acbdaffb8..d82eeba3a 100644
--- a/src/main/kotlin/org/rust/ide/refactoring/introduceVariable/impl.kt
+++ b/src/main/kotlin/org/rust/ide/refactoring/introduceVariable/impl.kt
@@ -14,6 +14,7 @@ import com.intellij.psi.util.PsiTreeUtil
 import org.rust.ide.refactoring.*
 import org.rust.lang.core.psi.*
 import org.rust.lang.core.psi.ext.ancestorOrSelf
+import org.rust.lang.core.psi.ext.ancestorStrict
 import org.rust.lang.core.psi.ext.startOffset
 import org.rust.openapiext.runWriteCommandAction
 
@@ -82,11 +83,12 @@ private class ExpressionReplacer(
         val suggestedNames = chosenExpr.suggestedNames()
         val let = createLet(suggestedNames.default)
         val name = psiFactory.createExpression(suggestedNames.default)
+        val parentLambda = chosenExpr.ancestorStrict<RsLambdaExpr>()
 
         project.runWriteCommandAction {
             val newElement = introduceLet(project, anchor, let)
             exprs.forEach { it.replace(name) }
-            val nameElem = moveEditorToNameElement(editor, newElement)
+            val nameElem = moveEditorToNameElement(editor, newElement.moveIntoLambdaBlockIfNeeded(parentLambda))
 
             if (nameElem != null) {
                 PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.document)
@@ -113,6 +115,15 @@ private class ExpressionReplacer(
         context.addAfter(newline, result)
         return result
     }
+
+    private fun PsiElement?.moveIntoLambdaBlockIfNeeded(lambda: RsLambdaExpr?): PsiElement? {
+        if (this == null) return this
+        val body = lambda?.expr ?: return this
+        if (body is RsBlockExpr) return this
+        val blockExpr = body.replace(RsPsiFactory(project).createBlockExpr("\\n${body.text}\\n")) as RsBlockExpr
+        val block = blockExpr.block
+        return block.addBefore(this, block.expr).also { this.delete() }
+    }
 }
 
 /**
diff --git a/src/test/kotlin/org/rust/ide/refactoring/RsIntroduceVariableHandlerTest.kt b/src/test/kotlin/org/rust/ide/refactoring/RsIntroduceVariableHandlerTest.kt
index 7e7cfde78..5a722a56b 100644
--- a/src/test/kotlin/org/rust/ide/refactoring/RsIntroduceVariableHandlerTest.kt
+++ b/src/test/kotlin/org/rust/ide/refactoring/RsIntroduceVariableHandlerTest.kt
@@ -302,6 +302,36 @@ class RsIntroduceVariableHandlerTest : RsTestBase() {
         }
     """)
 
+    fun `test lambda has no braces`() = doTest("""
+        fn main() {
+            Some(1).map(|x| <selection>x</selection> + 1);
+        }
+    """, emptyList(), 0, """
+        fn main() {
+            Some(1).map(|x| {
+                let x1 = x;
+                x1 + 1
+            });
+        }
+    """)
+
+    fun `test lambda has no braces with match expr`() = doTest("""
+        fn main() {
+            Some(1).map(|x| match <selection>x</selection> {
+                _ => 0,
+            });
+        }
+    """, emptyList(), 0, """
+        fn main() {
+            Some(1).map(|x| {
+                let x1 = x;
+                match x1 {
+                    _ => 0,
+                }
+            });
+        }
+    """)
+
     private fun doTest(
         @Language("Rust") before: String,
         expressions: List<String>,