about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <dylan.dpc@gmail.com>2020-05-14 18:21:46 +0200
committerGitHub <noreply@github.com>2020-05-14 18:21:46 +0200
commitb20b200d2edc22a97d8bf6a1621f37eacd9bc008 (patch)
tree8b30733ef5c395dac00ec95ff22b30afda5e743b
parentaf6d8865fe0e1f6338c32cb3370802f2ebca0dc4 (diff)
parent4b7a92838c98929a9f4c7a64583b5ea49ebb3a35 (diff)
downloadrust-b20b200d2edc22a97d8bf6a1621f37eacd9bc008.tar.gz
rust-b20b200d2edc22a97d8bf6a1621f37eacd9bc008.zip
Rollup merge of #71910 - mibac138:necessary-paren, r=cuviper
Fix unused_parens false positive when using binary operations

Fixes #71290

r? @cuviper who provided instructions
-rw-r--r--src/librustc_lint/unused.rs24
-rw-r--r--src/test/ui/lint/issue-71290-unused-paren-binop.rs23
2 files changed, 43 insertions, 4 deletions
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index ddd252cb290..c24079a6e4b 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -380,11 +380,27 @@ trait UnusedDelimLint {
     );
 
     fn is_expr_delims_necessary(inner: &ast::Expr, followed_by_block: bool) -> bool {
-        followed_by_block
-            && match inner.kind {
-                ExprKind::Ret(_) | ExprKind::Break(..) => true,
-                _ => parser::contains_exterior_struct_lit(&inner),
+        // Prevent false-positives in cases like `fn x() -> u8 { ({ 0 } + 1) }`
+        let lhs_needs_parens = {
+            let mut innermost = inner;
+            loop {
+                if let ExprKind::Binary(_, lhs, _rhs) = &innermost.kind {
+                    innermost = lhs;
+                    if !rustc_ast::util::classify::expr_requires_semi_to_be_stmt(innermost) {
+                        break true;
+                    }
+                } else {
+                    break false;
+                }
             }
+        };
+
+        lhs_needs_parens
+            || (followed_by_block
+                && match inner.kind {
+                    ExprKind::Ret(_) | ExprKind::Break(..) => true,
+                    _ => parser::contains_exterior_struct_lit(&inner),
+                })
     }
 
     fn emit_unused_delims_expr(
diff --git a/src/test/ui/lint/issue-71290-unused-paren-binop.rs b/src/test/ui/lint/issue-71290-unused-paren-binop.rs
new file mode 100644
index 00000000000..24d77e36d94
--- /dev/null
+++ b/src/test/ui/lint/issue-71290-unused-paren-binop.rs
@@ -0,0 +1,23 @@
+// check-pass
+// Make sure unused parens lint doesn't emit a false positive.
+// See https://github.com/rust-lang/rust/issues/71290 for details.
+#![deny(unused_parens)]
+
+fn x() -> u8 {
+    ({ 0 }) + 1
+}
+
+fn y() -> u8 {
+    ({ 0 } + 1)
+}
+
+pub fn foo(a: bool, b: bool) -> u8 {
+    (if a { 1 } else { 0 } + if b { 1 } else { 0 })
+}
+
+pub fn bar() -> u8 {
+    // Make sure nested expressions are handled correctly as well
+    ({ 0 } + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9)
+}
+
+fn main() {}