Add required parentheses around method receiver

This commit is contained in:
Samuel Tardieu 2024-05-25 18:08:14 +02:00
parent 1e23449678
commit 35b2aa99f3
4 changed files with 53 additions and 4 deletions

View File

@ -6,8 +6,8 @@
use clippy_utils::source::snippet_with_applicability; use clippy_utils::source::snippet_with_applicability;
use clippy_utils::sugg::Sugg; use clippy_utils::sugg::Sugg;
use clippy_utils::{ use clippy_utils::{
higher, is_block_like, is_else_clause, is_expn_of, is_parent_stmt, peel_blocks, peel_blocks_with_stmt, get_parent_expr, higher, is_block_like, is_else_clause, is_expn_of, is_parent_stmt, is_receiver_of_method_call,
span_extract_comment, SpanlessEq, peel_blocks, peel_blocks_with_stmt, span_extract_comment, SpanlessEq,
}; };
use rustc_ast::ast::LitKind; use rustc_ast::ast::LitKind;
use rustc_errors::Applicability; use rustc_errors::Applicability;
@ -154,7 +154,10 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
snip = snip.blockify(); snip = snip.blockify();
} }
if condition_needs_parentheses(cond) && is_parent_stmt(cx, e.hir_id) { if (condition_needs_parentheses(cond) && is_parent_stmt(cx, e.hir_id))
|| is_receiver_of_method_call(cx, e)
|| is_as_argument(cx, e)
{
snip = snip.maybe_par(); snip = snip.maybe_par();
} }
@ -442,3 +445,7 @@ fn fetch_assign<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<(&'tcx Expr<'tcx>, bool)
None None
} }
} }
fn is_as_argument(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
matches!(get_parent_expr(cx, e).map(|e| e.kind), Some(ExprKind::Cast(_, _)))
}

View File

@ -131,3 +131,15 @@ fn needless_bool_condition() -> bool {
foo() foo()
} }
fn issue12846() {
let a = true;
let b = false;
// parentheses are needed here
let _x = (a && b).then(|| todo!());
let _x = (a && b) as u8;
// parentheses are not needed here
let _x = a.then(|| todo!());
}

View File

@ -191,3 +191,15 @@ fn foo() -> bool {
foo() foo()
} }
fn issue12846() {
let a = true;
let b = false;
// parentheses are needed here
let _x = if a && b { true } else { false }.then(|| todo!());
let _x = if a && b { true } else { false } as u8;
// parentheses are not needed here
let _x = if a { true } else { false }.then(|| todo!());
}

View File

@ -191,5 +191,23 @@ error: this if-then-else expression returns a bool literal
LL | if unsafe { no(4) } & 1 != 0 { true } else { false } LL | if unsafe { no(4) } & 1 != 0 { true } else { false }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `(unsafe { no(4) } & 1 != 0)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `(unsafe { no(4) } & 1 != 0)`
error: aborting due to 21 previous errors error: this if-then-else expression returns a bool literal
--> tests/ui/needless_bool/fixable.rs:200:14
|
LL | let _x = if a && b { true } else { false }.then(|| todo!());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `(a && b)`
error: this if-then-else expression returns a bool literal
--> tests/ui/needless_bool/fixable.rs:201:14
|
LL | let _x = if a && b { true } else { false } as u8;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `(a && b)`
error: this if-then-else expression returns a bool literal
--> tests/ui/needless_bool/fixable.rs:204:14
|
LL | let _x = if a { true } else { false }.then(|| todo!());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `a`
error: aborting due to 24 previous errors