about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-06-24 08:25:49 +0000
committerbors <bors@rust-lang.org>2024-06-24 08:25:49 +0000
commit1cd8bc0cf2e84207adf59165f5c433aebd142103 (patch)
treea78eadc231d37899da42359cb7a0fd1371ba452f /src
parentf9a337cc881aba5f4acdc07dffc16a0bb76da99f (diff)
parentf1debd96e458542a484fd1d0d0b709c9d7516b7c (diff)
downloadrust-1cd8bc0cf2e84207adf59165f5c433aebd142103.tar.gz
rust-1cd8bc0cf2e84207adf59165f5c433aebd142103.zip
Auto merge of #17471 - davidsemakula:fix-remove-parenthesis, r=Veykril
fix: don't remove parentheses for calls of function-like pointers that are members of a struct or union

Fixes #17111
Diffstat (limited to 'src')
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs29
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/prec.rs8
2 files changed, 37 insertions, 0 deletions
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs
index 799d36be93e..f74fc261128 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs
@@ -239,4 +239,33 @@ mod tests {
 
         check_assist_not_applicable(remove_parentheses, r#"fn f() { $0(return 2) + 2 }"#);
     }
+
+    #[test]
+    fn remove_parens_indirect_calls() {
+        check_assist(
+            remove_parentheses,
+            r#"fn f(call: fn(usize), arg: usize) { $0(call)(arg); }"#,
+            r#"fn f(call: fn(usize), arg: usize) { call(arg); }"#,
+        );
+        check_assist(
+            remove_parentheses,
+            r#"fn f<F>(call: F, arg: usize) where F: Fn(usize) { $0(call)(arg); }"#,
+            r#"fn f<F>(call: F, arg: usize) where F: Fn(usize) { call(arg); }"#,
+        );
+
+        // Parentheses are necessary when calling a function-like pointer that is a member of a struct or union.
+        check_assist_not_applicable(
+            remove_parentheses,
+            r#"
+struct Foo<T> {
+    t: T,
+}
+
+impl Foo<fn(usize)> {
+    fn foo(&self, arg: usize) {
+        $0(self.t)(arg);
+    }
+}"#,
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/prec.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/prec.rs
index 9131cd2f179..28089ffb377 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/prec.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/prec.rs
@@ -27,6 +27,14 @@ impl Expr {
     }
 
     fn needs_parens_in_expr(&self, parent: &Expr) -> bool {
+        // Parentheses are necessary when calling a function-like pointer that is a member of a struct or union
+        // (e.g. `(a.f)()`).
+        let is_parent_call_expr = matches!(parent, ast::Expr::CallExpr(_));
+        let is_field_expr = matches!(self, ast::Expr::FieldExpr(_));
+        if is_parent_call_expr && is_field_expr {
+            return true;
+        }
+
         // Special-case block weirdness
         if parent.child_is_followed_by_a_block() {
             use Expr::*;