about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorA4-Tacks <wdsjxhno1001@163.com>2025-09-14 00:42:11 +0800
committerA4-Tacks <wdsjxhno1001@163.com>2025-09-20 20:56:27 +0800
commit71fdb598c7d8a2b85d757c361c812b33b7433a10 (patch)
tree7bb699ef75bb5660a980ce1d337e44647f9fc7f6 /src
parente976c9c762e1d19e177e41a9fe2b2a397229f8c4 (diff)
downloadrust-71fdb598c7d8a2b85d757c361c812b33b7433a10.tar.gz
rust-71fdb598c7d8a2b85d757c361c812b33b7433a10.zip
Fix IfExpr then branch suggest
- And add logic operation suggest

Example
---
In the old implementation, it always suggested conditions,
this is a lot of noise, e.g `contract_checks()~(use std::intrinsics::contract_checks) const fn() -> bool`

```rust
fn foo() {
    if true {
        c$0
    }
}
```
Diffstat (limited to 'src')
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs13
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs69
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs8
3 files changed, 82 insertions, 8 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 7b78a9700ec..cdb1ad8b38e 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
@@ -637,6 +637,9 @@ fn expected_type_and_name<'db>(
                             .or_else(|| it.rhs().and_then(|rhs| sema.type_of_expr(&rhs)))
                             .map(TypeInfo::original);
                         (ty, None)
+                    } else if let Some(ast::BinaryOp::LogicOp(_)) = it.op_kind() {
+                        let ty = sema.type_of_expr(&it.clone().into()).map(TypeInfo::original);
+                        (ty, None)
                     } else {
                         (None, None)
                     }
@@ -707,9 +710,13 @@ fn expected_type_and_name<'db>(
                     (ty, None)
                 },
                 ast::IfExpr(it) => {
-                    let ty = it.condition()
-                        .and_then(|e| sema.type_of_expr(&e))
-                        .map(TypeInfo::original);
+                    let ty = if let Some(body) = it.then_branch()
+                        && token.text_range().end() > body.syntax().text_range().start()
+                    {
+                        sema.type_of_expr(&body.into())
+                    } else {
+                        it.condition().and_then(|e| sema.type_of_expr(&e))
+                    }.map(TypeInfo::original);
                     (ty, None)
                 },
                 ast::IdentPat(it) => {
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 445afa75f3f..d9ec7915e3c 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
@@ -279,6 +279,62 @@ fn foo() {
 }
 
 #[test]
+fn expected_type_if_let_chain_bool() {
+    check_expected_type_and_name(
+        r#"
+fn foo() {
+    let f = Foo::Quux;
+    if let c = f && $0 { }
+}
+"#,
+        expect![[r#"ty: bool, name: ?"#]],
+    );
+}
+
+#[test]
+fn expected_type_if_condition() {
+    check_expected_type_and_name(
+        r#"
+fn foo() {
+    if a$0 { }
+}
+"#,
+        expect![[r#"ty: bool, name: ?"#]],
+    );
+}
+
+#[test]
+fn expected_type_if_body() {
+    check_expected_type_and_name(
+        r#"
+enum Foo { Bar, Baz, Quux }
+
+fn foo() {
+    let _: Foo = if true {
+        $0
+    };
+}
+"#,
+        expect![[r#"ty: Foo, name: ?"#]],
+    );
+
+    check_expected_type_and_name(
+        r#"
+enum Foo { Bar, Baz, Quux }
+
+fn foo() {
+    let _: Foo = if true {
+        Foo::Bar
+    } else {
+        $0
+    };
+}
+"#,
+        expect![[r#"ty: Foo, name: ?"#]],
+    );
+}
+
+#[test]
 fn expected_type_fn_ret_without_leading_char() {
     cov_mark::check!(expected_type_fn_ret_without_leading_char);
     check_expected_type_and_name(
@@ -526,3 +582,16 @@ fn foo() {
         expect![[r#"ty: State, name: ?"#]],
     );
 }
+
+#[test]
+fn expected_type_logic_op() {
+    check_expected_type_and_name(
+        r#"
+enum State { Stop }
+fn foo() {
+    true && $0;
+}
+"#,
+        expect![[r#"ty: bool, name: ?"#]],
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
index c420953036f..98a6f95f334 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
@@ -271,8 +271,6 @@ fn complete_in_block() {
             sn macro_rules
             sn pd
             sn ppd
-            ex false
-            ex true
         "#]],
     )
 }
@@ -1668,7 +1666,7 @@ fn foo() { let x = if foo {} $0; let y = 92; }
 fn foo() { let x = if foo {} $0 else {}; }
 "#,
         expect![[r#"
-            fn foo    fn()
+            fn foo()  fn()
             bt u32     u32
             kw async
             kw const
@@ -1710,7 +1708,7 @@ fn foo() { let x = if foo {} $0 else {}; }
 fn foo() { let x = if foo {} $0 else if true {}; }
 "#,
         expect![[r#"
-            fn foo    fn()
+            fn foo()  fn()
             bt u32     u32
             kw async
             kw const
@@ -1795,7 +1793,7 @@ fn foo() { let x = if foo {} el$0 else if true {} else {}; }
 fn foo() { let x = if foo {} $0 else if true {} else {}; }
 "#,
         expect![[r#"
-            fn foo    fn()
+            fn foo()  fn()
             bt u32     u32
             kw async
             kw const