about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorChayim Refael Friedman <chayimfr@gmail.com>2025-08-24 00:46:49 +0000
committerGitHub <noreply@github.com>2025-08-24 00:46:49 +0000
commitd50f0c72f93ff7624de90d44b24dbb7e1659636c (patch)
treeb035c333d86f5887ef37daa4729f285e7697a6b4 /src
parent6de4860541fd1b66c6ada2a3ce688cef98e38586 (diff)
parentc92af4d23285428c92e67fedb6d73a9a86a90cff (diff)
downloadrust-d50f0c72f93ff7624de90d44b24dbb7e1659636c.tar.gz
rust-d50f0c72f93ff7624de90d44b24dbb7e1659636c.zip
Merge pull request #20507 from A4-Tacks/suggest-return-expr
Add ReturnExpr completion suggest
Diffstat (limited to 'src')
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs21
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs36
2 files changed, 54 insertions, 3 deletions
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
index df1924ac1c2..17978b4c107 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
@@ -559,7 +559,7 @@ fn expected_type_and_name<'db>(
     token: &SyntaxToken,
     name_like: &ast::NameLike,
 ) -> (Option<Type<'db>>, Option<NameOrNameRef>) {
-    let token = prev_assign_token_at_trivia(token.clone());
+    let token = prev_special_biased_token_at_trivia(token.clone());
     let mut node = match token.parent() {
         Some(it) => it,
         None => return (None, None),
@@ -724,6 +724,18 @@ fn expected_type_and_name<'db>(
                     let def = sema.to_def(&it);
                     (def.map(|def| def.ret_type(sema.db)), None)
                 },
+                ast::ReturnExpr(it) => {
+                    let fn_ = sema.ancestors_with_macros(it.syntax().clone())
+                        .find_map(Either::<ast::Fn, ast::ClosureExpr>::cast);
+                    let ty = fn_.and_then(|f| match f {
+                        Either::Left(f) => Some(sema.to_def(&f)?.ret_type(sema.db)),
+                        Either::Right(f) => {
+                            let ty = sema.type_of_expr(&f.into())?.original.as_callable(sema.db)?;
+                            Some(ty.return_type())
+                        },
+                    });
+                    (ty, None)
+                },
                 ast::ClosureExpr(it) => {
                     let ty = sema.type_of_expr(&it.into());
                     ty.and_then(|ty| ty.original.as_callable(sema.db))
@@ -1877,7 +1889,7 @@ fn next_non_trivia_sibling(ele: SyntaxElement) -> Option<SyntaxElement> {
     None
 }
 
-fn prev_assign_token_at_trivia(mut token: SyntaxToken) -> SyntaxToken {
+fn prev_special_biased_token_at_trivia(mut token: SyntaxToken) -> SyntaxToken {
     while token.kind().is_trivia()
         && let Some(prev) = token.prev_token()
         && let T![=]
@@ -1890,7 +1902,10 @@ fn prev_assign_token_at_trivia(mut token: SyntaxToken) -> SyntaxToken {
         | T![-=]
         | T![|=]
         | T![&=]
-        | T![^=] = prev.kind()
+        | T![^=]
+        | T![return]
+        | T![break]
+        | T![continue] = prev.kind()
     {
         token = prev
     }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs
index f03f61d10e5..6121c61ea3f 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs
@@ -489,3 +489,39 @@ fn foo() {
         expect![[r#"ty: State, name: ?"#]],
     );
 }
+
+#[test]
+fn expected_type_return_expr() {
+    check_expected_type_and_name(
+        r#"
+enum State { Stop }
+fn foo() -> State {
+    let _: i32 = if true {
+        8
+    } else {
+        return $0;
+    };
+}
+"#,
+        expect![[r#"ty: State, name: ?"#]],
+    );
+}
+
+#[test]
+fn expected_type_return_expr_in_closure() {
+    check_expected_type_and_name(
+        r#"
+enum State { Stop }
+fn foo() {
+    let _f: fn() -> State = || {
+        let _: i32 = if true {
+            8
+        } else {
+            return $0;
+        };
+    };
+}
+"#,
+        expect![[r#"ty: State, name: ?"#]],
+    );
+}