Repository: intellij-rust/intellij-rust
Issue: Fails to inline functions like async fn foo() -> Result<()>

## Environment

* **IntelliJ Rust plugin version:** 0.4.191.5293-231
* **Rust toolchain version:** 1.70.0-nightly (22f247c6f 2023-03-13) aarch64-apple-darwin
* **IDE name and version:** CLion 2023.1.1 (CL-231.8109.222)
* **Operating system:** macOS 13.2.1
* **Macro expansion:** enabled

## Problem description
```rust
use eyre::Result;
async fn test_inline() -> Result<()> {
    let x = foo().await?;
    Ok(())
}
async fn foo() -> Result<()> {
    let a = 1;
    Ok(a)
}
```
after inlining foo(), I got
```rust
use eyre::Result;

async fn test_inline() -> Result<()> {
    let a = 1;
    let x = Ok(a).await?;
    Ok(())
}
```

It has two problems.

1. Ok(a)? is unnecessary
2. usage of await is incorrect and it doesn't compile anymore

Changed files:
src/test/kotlin/org/rust/ide/refactoring/inlineFunction/RsInlineFunctionTest2.kt
src/main/kotlin/org/rust/lang/core/psi/ext/RsElement.kt
src/main/kotlin/org/rust/ide/refactoring/inlineFunction/RsInlineFunctionProcessor.kt

diff --git a/src/main/kotlin/org/rust/ide/refactoring/inlineFunction/RsInlineFunctionProcessor.kt b/src/main/kotlin/org/rust/ide/refactoring/inlineFunction/RsInlineFunctionProcessor.kt
index 45ba1b034..a5324dc21 100644
--- a/src/main/kotlin/org/rust/ide/refactoring/inlineFunction/RsInlineFunctionProcessor.kt
+++ b/src/main/kotlin/org/rust/ide/refactoring/inlineFunction/RsInlineFunctionProcessor.kt
@@ -122,8 +122,7 @@ class RsInlineFunctionProcessor(
             handleUsage(usage, function)
         }
         if (removeDefinition && handledUsages.size == usages.size) {
-            (originalFunction.prevSibling as? PsiWhiteSpace)?.delete()
-            originalFunction.delete()
+            originalFunction.deleteWithPreviousWhitespace()
         }
     }
 
@@ -249,10 +248,7 @@ private class InlineSingleUsage(
 ) {
 
     /** The expression which should be replaced by function body */
-    private val functionCall: RsExpr = when (usage) {
-        is FunctionCallUsage -> usage.functionCall
-        is MethodCallUsage -> usage.methodCall.parent as RsDotExpr
-    }
+    private val functionCall: RsExpr = prepareFunctionCall(usage)
     private val factory: RsPsiFactory = RsPsiFactory(functionCall.project)
     private val function: RsFunction = preprocessFunction(function)
 
@@ -410,6 +406,23 @@ private class InlineSingleUsage(
         return declarationLastUsages.any { it is RsPathExpr && it.path == usage }
     }
 
+    private fun prepareFunctionCall(usage: CallUsage): RsExpr {
+        val functionCall = when (usage) {
+            is FunctionCallUsage -> usage.functionCall
+            is MethodCallUsage -> usage.methodCall.parent as RsDotExpr
+        }
+        return functionCall.unwrapAwait() ?: functionCall
+    }
+
+    // `foo().await` -> `foo()`
+    //  ~~~~~ [this]
+    private fun RsExpr.unwrapAwait(): RsExpr? {
+        if (!originalFunction.isAsync) return null
+        val parent = parent as? RsDotExpr
+        if (parent?.fieldLookup?.isAsync != true) return null
+        return parent.replace(this) as RsExpr
+    }
+
     private fun preprocessFunction(originalFunction: RsFunction): RsFunction {
         val outerScopeNames = functionCall.getAllVisibleBindingsIncludingContainingLetDeclaration()
         val functionNames = function.descendantsOfType<RsNameIdentifierOwner>().mapNotNullTo(hashSetOf()) { it.name }
diff --git a/src/main/kotlin/org/rust/lang/core/psi/ext/RsElement.kt b/src/main/kotlin/org/rust/lang/core/psi/ext/RsElement.kt
index 9e79308ec..01a3afa96 100644
--- a/src/main/kotlin/org/rust/lang/core/psi/ext/RsElement.kt
+++ b/src/main/kotlin/org/rust/lang/core/psi/ext/RsElement.kt
@@ -219,6 +219,16 @@ fun RsElement.deleteWithSurroundingPlus() {
     delete()
 }
 
+fun RsElement.deleteWithPreviousWhitespace() {
+    val whitespace = prevSibling as? PsiWhiteSpace
+    if (whitespace != null) {
+        // separate deletion of [whitespace] can lead to addition of new space
+        parent.deleteChildRange(whitespace, this)
+    } else {
+        delete()
+    }
+}
+
 private val PsiElement.isWhitespaceOrComment
     get(): Boolean = this is PsiWhiteSpace || this is PsiComment
 
diff --git a/src/test/kotlin/org/rust/ide/refactoring/inlineFunction/RsInlineFunctionTest2.kt b/src/test/kotlin/org/rust/ide/refactoring/inlineFunction/RsInlineFunctionTest2.kt
index dc1874d58..6c5192811 100644
--- a/src/test/kotlin/org/rust/ide/refactoring/inlineFunction/RsInlineFunctionTest2.kt
+++ b/src/test/kotlin/org/rust/ide/refactoring/inlineFunction/RsInlineFunctionTest2.kt
@@ -1033,4 +1033,85 @@ class RsInlineFunctionTest2 : RsInlineTestBase() {
             let _ = (2 + 1) + 1;
         }
     """)
+
+    fun `test async function used as stmt 1`() = doTest("""
+        async fn test() {
+            foo().await;
+        }
+        async fn /*caret*/foo() {
+            println!();
+        }
+    """, """
+        async fn test() {
+            println!();
+        }
+    """)
+
+    fun `test async function used as stmt 2`() = doTest("""
+        async fn test() {
+            foo().await;
+        }
+        async fn /*caret*/foo() {
+            bar().await;
+            bar().await;
+        }
+        async fn bar() {}
+    """, """
+        async fn test() {
+            bar().await;
+            bar().await;
+        }
+
+        async fn bar() {}
+    """)
+
+    fun `test async function used as expr 1`() = doTest("""
+        async fn test() {
+            consume(foo().await);
+        }
+        async fn /*caret*/foo() -> i32 {
+            0
+        }
+    """, """
+        async fn test() {
+            consume(0);
+        }
+    """)
+
+    fun `test async function used as expr 2`() = doTest("""
+        async fn test() {
+            consume(foo().await);
+        }
+        async fn /*caret*/foo() -> i32 {
+            bar().await
+        }
+        async fn bar() -> i32 { 0 }
+    """, """
+        async fn test() {
+            consume(bar().await);
+        }
+
+        async fn bar() -> i32 { 0 }
+    """)
+
+    @ProjectDescriptor(WithStdlibRustProjectDescriptor::class)
+    fun `test non-async function returning Future`() = doTest("""
+        use std::future::Future;
+        async fn test() {
+            let x = foo().await;
+        }
+        fn /*caret*/foo() -> impl Future<Output=i32> {
+            println!();
+            bar()
+        }
+        async fn bar() -> i32 { 0 }
+    """, """
+        use std::future::Future;
+        async fn test() {
+            println!();
+            let x = bar().await;
+        }
+
+        async fn bar() -> i32 { 0 }
+    """)
 }