Skip to content

Commit f1debd9

Browse files
committed
fix: don't remove parentheses for calls of function-like pointers that are members of a struct or union
1 parent 9b8b6f9 commit f1debd9

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,4 +239,33 @@ mod tests {
239239

240240
check_assist_not_applicable(remove_parentheses, r#"fn f() { $0(return 2) + 2 }"#);
241241
}
242+
243+
#[test]
244+
fn remove_parens_indirect_calls() {
245+
check_assist(
246+
remove_parentheses,
247+
r#"fn f(call: fn(usize), arg: usize) { $0(call)(arg); }"#,
248+
r#"fn f(call: fn(usize), arg: usize) { call(arg); }"#,
249+
);
250+
check_assist(
251+
remove_parentheses,
252+
r#"fn f<F>(call: F, arg: usize) where F: Fn(usize) { $0(call)(arg); }"#,
253+
r#"fn f<F>(call: F, arg: usize) where F: Fn(usize) { call(arg); }"#,
254+
);
255+
256+
// Parentheses are necessary when calling a function-like pointer that is a member of a struct or union.
257+
check_assist_not_applicable(
258+
remove_parentheses,
259+
r#"
260+
struct Foo<T> {
261+
t: T,
262+
}
263+
264+
impl Foo<fn(usize)> {
265+
fn foo(&self, arg: usize) {
266+
$0(self.t)(arg);
267+
}
268+
}"#,
269+
);
270+
}
242271
}

src/tools/rust-analyzer/crates/syntax/src/ast/prec.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ impl Expr {
2727
}
2828

2929
fn needs_parens_in_expr(&self, parent: &Expr) -> bool {
30+
// Parentheses are necessary when calling a function-like pointer that is a member of a struct or union
31+
// (e.g. `(a.f)()`).
32+
let is_parent_call_expr = matches!(parent, ast::Expr::CallExpr(_));
33+
let is_field_expr = matches!(self, ast::Expr::FieldExpr(_));
34+
if is_parent_call_expr && is_field_expr {
35+
return true;
36+
}
37+
3038
// Special-case block weirdness
3139
if parent.child_is_followed_by_a_block() {
3240
use Expr::*;

0 commit comments

Comments
 (0)