diff --git a/crates/ide-assists/src/handlers/remove_parentheses.rs b/crates/ide-assists/src/handlers/remove_parentheses.rs index d514c1c29158..fb051e5b5780 100644 --- a/crates/ide-assists/src/handlers/remove_parentheses.rs +++ b/crates/ide-assists/src/handlers/remove_parentheses.rs @@ -162,6 +162,30 @@ mod tests { check_assist_not_applicable(remove_parentheses, r#"fn f() { if $0(return) {} }"#); } + #[test] + fn remove_parens_prefix_with_return_no_value() { + // removing `()` from !(return) would make `!return` which is invalid syntax + check_assist_not_applicable( + remove_parentheses, + r#"fn main() { let _x = true && !$0(return) || true; }"#, + ); + check_assist_not_applicable(remove_parentheses, r#"fn f() { !$0(return) }"#); + check_assist_not_applicable(remove_parentheses, r#"fn f() { !$0(break) }"#); + check_assist_not_applicable(remove_parentheses, r#"fn f() { !$0(continue) }"#); + + // Binary operators should still allow removal + check_assist( + remove_parentheses, + r#"fn f() { true || $0(return) }"#, + r#"fn f() { true || return }"#, + ); + check_assist( + remove_parentheses, + r#"fn f() { cond && $0(return) }"#, + r#"fn f() { cond && return }"#, + ); + } + #[test] fn remove_parens_return_with_value_followed_by_block() { check_assist( diff --git a/crates/syntax/src/ast/prec.rs b/crates/syntax/src/ast/prec.rs index 1364adb187fc..2e58f7be2925 100644 --- a/crates/syntax/src/ast/prec.rs +++ b/crates/syntax/src/ast/prec.rs @@ -226,6 +226,12 @@ impl Expr { return false; } + // Special-case prefix operators with return/break/etc without value + // e.g., `!(return)` - parentheses are necessary + if self.is_ret_like_with_no_value() && parent.is_prefix() { + return true; + } + if self.is_paren_like() || parent.is_paren_like() || self.is_prefix()