diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 80a64e59c0f0e..d677d51881e0e 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -569,36 +569,50 @@ trait UnusedDelimLint { } } - // Prevent false-positives in cases like `fn x() -> u8 { ({ 0 } + 1) }` - let lhs_needs_parens = { + // Check if LHS needs parens to prevent false-positives in cases like `fn x() -> u8 { ({ 0 } + 1) }`. + { let mut innermost = inner; loop { innermost = match &innermost.kind { - ExprKind::Binary(_, lhs, _rhs) => lhs, + ExprKind::Binary(_op, lhs, _rhs) => lhs, ExprKind::Call(fn_, _params) => fn_, ExprKind::Cast(expr, _ty) => expr, ExprKind::Type(expr, _ty) => expr, ExprKind::Index(base, _subscript) => base, - _ => break false, + _ => break, }; if !classify::expr_requires_semi_to_be_stmt(innermost) { - break true; + return true; } } - }; + } - lhs_needs_parens - || (followed_by_block - && match &inner.kind { - ExprKind::Ret(_) - | ExprKind::Break(..) - | ExprKind::Yield(..) - | ExprKind::Yeet(..) => true, - ExprKind::Range(_lhs, Some(rhs), _limits) => { - matches!(rhs.kind, ExprKind::Block(..)) - } - _ => parser::contains_exterior_struct_lit(&inner), - }) + // Check if RHS needs parens to prevent false-positives in cases like `if (() == return) {}`. + if !followed_by_block { + return false; + } + let mut innermost = inner; + loop { + innermost = match &innermost.kind { + ExprKind::Unary(_op, expr) => expr, + ExprKind::Binary(_op, _lhs, rhs) => rhs, + ExprKind::AssignOp(_op, _lhs, rhs) => rhs, + ExprKind::Assign(_lhs, rhs, _span) => rhs, + + ExprKind::Ret(_) | ExprKind::Yield(..) | ExprKind::Yeet(..) => return true, + + ExprKind::Break(_label, None) => return false, + ExprKind::Break(_label, Some(break_expr)) => { + return matches!(break_expr.kind, ExprKind::Block(..)); + } + + ExprKind::Range(_lhs, Some(rhs), _limits) => { + return matches!(rhs.kind, ExprKind::Block(..)); + } + + _ => return parser::contains_exterior_struct_lit(&inner), + } + } } fn emit_unused_delims_expr( diff --git a/tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed b/tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed index 71ebaea8ed2c1..9c52ca5577e4a 100644 --- a/tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed +++ b/tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed @@ -21,17 +21,32 @@ fn lint_on_top_level() { let _ = |a: u8| 0; //~ ERROR unnecessary parentheses around pattern } -fn _no_lint_attr() { +fn no_lint_attr() { let _x = #[allow(dead_code)] (1 + 2); } -fn _no_lint_yeet() -> Result<(), ()> { +fn no_lint_yeet() -> Result<(), ()> { #[allow(unreachable_code)] if (do yeet) {} Ok(()) } +fn no_lint_ops() { + #![allow(unreachable_code, irrefutable_let_patterns)] + if ((..{}) == ..{}) {} + if (!return) {} + loop { match (() = () = () = break {}) {} } + while let () = (*&mut false |= true && return) {} +} + +fn lint_break_if_not_followed_by_block() { + #![allow(unreachable_code)] + loop { if break {} } //~ ERROR unnecessary parentheses + loop { if break ({ println!("hello") }) {} } //~ ERROR unnecessary parentheses + loop { if (break { println!("hello") }) {} } +} + // Don't lint in these cases (#64106). fn or_patterns_no_lint() { match Box::new(0) { diff --git a/tests/ui/lint/unused/issue-54538-unused-parens-lint.rs b/tests/ui/lint/unused/issue-54538-unused-parens-lint.rs index 28b662dd0242c..196ecf0c1bb85 100644 --- a/tests/ui/lint/unused/issue-54538-unused-parens-lint.rs +++ b/tests/ui/lint/unused/issue-54538-unused-parens-lint.rs @@ -21,17 +21,32 @@ fn lint_on_top_level() { let _ = |(a): u8| 0; //~ ERROR unnecessary parentheses around pattern } -fn _no_lint_attr() { +fn no_lint_attr() { let _x = #[allow(dead_code)] (1 + 2); } -fn _no_lint_yeet() -> Result<(), ()> { +fn no_lint_yeet() -> Result<(), ()> { #[allow(unreachable_code)] if (do yeet) {} Ok(()) } +fn no_lint_ops() { + #![allow(unreachable_code, irrefutable_let_patterns)] + if ((..{}) == ..{}) {} + if (!return) {} + loop { match (() = () = () = break {}) {} } + while let () = (*&mut false |= true && return) {} +} + +fn lint_break_if_not_followed_by_block() { + #![allow(unreachable_code)] + loop { if (break) {} } //~ ERROR unnecessary parentheses + loop { if (break ({ println!("hello") })) {} } //~ ERROR unnecessary parentheses + loop { if (break { println!("hello") }) {} } +} + // Don't lint in these cases (#64106). fn or_patterns_no_lint() { match Box::new(0) { diff --git a/tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr b/tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr index a5e69e6d9385c..f916bba8194ff 100644 --- a/tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr +++ b/tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr @@ -75,8 +75,32 @@ LL - let _ = |(a): u8| 0; LL + let _ = |a: u8| 0; | +error: unnecessary parentheses around `if` condition + --> $DIR/issue-54538-unused-parens-lint.rs:45:15 + | +LL | loop { if (break) {} } + | ^ ^ + | +help: remove these parentheses + | +LL - loop { if (break) {} } +LL + loop { if break {} } + | + +error: unnecessary parentheses around `if` condition + --> $DIR/issue-54538-unused-parens-lint.rs:46:15 + | +LL | loop { if (break ({ println!("hello") })) {} } + | ^ ^ + | +help: remove these parentheses + | +LL - loop { if (break ({ println!("hello") })) {} } +LL + loop { if break ({ println!("hello") }) {} } + | + error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:56:12 + --> $DIR/issue-54538-unused-parens-lint.rs:71:12 | LL | if let (0 | 1) = 0 {} | ^ ^ @@ -88,7 +112,7 @@ LL + if let 0 | 1 = 0 {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:57:13 + --> $DIR/issue-54538-unused-parens-lint.rs:72:13 | LL | if let ((0 | 1),) = (0,) {} | ^ ^ @@ -100,7 +124,7 @@ LL + if let (0 | 1,) = (0,) {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:58:13 + --> $DIR/issue-54538-unused-parens-lint.rs:73:13 | LL | if let [(0 | 1)] = [0] {} | ^ ^ @@ -112,7 +136,7 @@ LL + if let [0 | 1] = [0] {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:59:16 + --> $DIR/issue-54538-unused-parens-lint.rs:74:16 | LL | if let 0 | (1 | 2) = 0 {} | ^ ^ @@ -124,7 +148,7 @@ LL + if let 0 | 1 | 2 = 0 {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:61:15 + --> $DIR/issue-54538-unused-parens-lint.rs:76:15 | LL | if let TS((0 | 1)) = TS(0) {} | ^ ^ @@ -136,7 +160,7 @@ LL + if let TS(0 | 1) = TS(0) {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:63:20 + --> $DIR/issue-54538-unused-parens-lint.rs:78:20 | LL | if let NS { f: (0 | 1) } = (NS { f: 0 }) {} | ^ ^ @@ -148,7 +172,7 @@ LL + if let NS { f: 0 | 1 } = (NS { f: 0 }) {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:73:9 + --> $DIR/issue-54538-unused-parens-lint.rs:88:9 | LL | (_) => {} | ^ ^ @@ -160,7 +184,7 @@ LL + _ => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:74:9 + --> $DIR/issue-54538-unused-parens-lint.rs:89:9 | LL | (y) => {} | ^ ^ @@ -172,7 +196,7 @@ LL + y => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:75:9 + --> $DIR/issue-54538-unused-parens-lint.rs:90:9 | LL | (ref r) => {} | ^ ^ @@ -184,7 +208,7 @@ LL + ref r => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:76:9 + --> $DIR/issue-54538-unused-parens-lint.rs:91:9 | LL | (e @ 1...2) => {} | ^ ^ @@ -196,7 +220,7 @@ LL + e @ 1...2 => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:82:9 + --> $DIR/issue-54538-unused-parens-lint.rs:97:9 | LL | (e @ &(1...2)) => {} | ^ ^ @@ -208,7 +232,7 @@ LL + e @ &(1...2) => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:83:10 + --> $DIR/issue-54538-unused-parens-lint.rs:98:10 | LL | &(_) => {} | ^ ^ @@ -220,7 +244,7 @@ LL + &_ => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:94:9 + --> $DIR/issue-54538-unused-parens-lint.rs:109:9 | LL | (_) => {} | ^ ^ @@ -232,7 +256,7 @@ LL + _ => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:95:9 + --> $DIR/issue-54538-unused-parens-lint.rs:110:9 | LL | (y) => {} | ^ ^ @@ -244,7 +268,7 @@ LL + y => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:96:9 + --> $DIR/issue-54538-unused-parens-lint.rs:111:9 | LL | (ref r) => {} | ^ ^ @@ -256,7 +280,7 @@ LL + ref r => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:97:9 + --> $DIR/issue-54538-unused-parens-lint.rs:112:9 | LL | (e @ 1..=2) => {} | ^ ^ @@ -268,7 +292,7 @@ LL + e @ 1..=2 => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:103:9 + --> $DIR/issue-54538-unused-parens-lint.rs:118:9 | LL | (e @ &(1..=2)) => {} | ^ ^ @@ -280,7 +304,7 @@ LL + e @ &(1..=2) => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:104:10 + --> $DIR/issue-54538-unused-parens-lint.rs:119:10 | LL | &(_) => {} | ^ ^ @@ -291,5 +315,5 @@ LL - &(_) => {} LL + &_ => {} | -error: aborting due to 24 previous errors +error: aborting due to 26 previous errors