From 2fe73cea5ef8e381e47161468167c90ed3fb724a Mon Sep 17 00:00:00 2001
From: yukang <moorekang@gmail.com>
Date: Wed, 14 Feb 2024 15:15:22 +0800
Subject: [PATCH] Fix false positive with if let and ranges

---
 compiler/rustc_lint/src/unused.rs       | 16 ++++++++++++----
 tests/ui/lint/issue-121070-let-range.rs | 16 ++++++++++++++++
 2 files changed, 28 insertions(+), 4 deletions(-)
 create mode 100644 tests/ui/lint/issue-121070-let-range.rs

diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 9f670893b27..35ee0c53046 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -651,9 +651,11 @@ trait UnusedDelimLint {
 
     fn is_expr_delims_necessary(
         inner: &ast::Expr,
+        ctx: UnusedDelimsCtx,
         followed_by_block: bool,
-        followed_by_else: bool,
     ) -> bool {
+        let followed_by_else = ctx == UnusedDelimsCtx::AssignedValueLetElse;
+
         if followed_by_else {
             match inner.kind {
                 ast::ExprKind::Binary(op, ..) if op.node.is_lazy() => return true,
@@ -662,6 +664,13 @@ trait UnusedDelimLint {
             }
         }
 
+        // Check it's range in LetScrutineeExpr
+        if let ast::ExprKind::Range(..) = inner.kind
+            && matches!(ctx, UnusedDelimsCtx::LetScrutineeExpr)
+        {
+            return true;
+        }
+
         // Check if LHS needs parens to prevent false-positives in cases like `fn x() -> u8 { ({ 0 } + 1) }`.
         {
             let mut innermost = inner;
@@ -1007,8 +1016,7 @@ impl UnusedDelimLint for UnusedParens {
     ) {
         match value.kind {
             ast::ExprKind::Paren(ref inner) => {
-                let followed_by_else = ctx == UnusedDelimsCtx::AssignedValueLetElse;
-                if !Self::is_expr_delims_necessary(inner, followed_by_block, followed_by_else)
+                if !Self::is_expr_delims_necessary(inner, ctx, followed_by_block)
                     && value.attrs.is_empty()
                     && !value.span.from_expansion()
                     && (ctx != UnusedDelimsCtx::LetScrutineeExpr
@@ -1334,7 +1342,7 @@ impl UnusedDelimLint for UnusedBraces {
                 // FIXME(const_generics): handle paths when #67075 is fixed.
                 if let [stmt] = inner.stmts.as_slice() {
                     if let ast::StmtKind::Expr(ref expr) = stmt.kind {
-                        if !Self::is_expr_delims_necessary(expr, followed_by_block, false)
+                        if !Self::is_expr_delims_necessary(expr, ctx, followed_by_block)
                             && (ctx != UnusedDelimsCtx::AnonConst
                                 || (matches!(expr.kind, ast::ExprKind::Lit(_))
                                     && !expr.span.from_expansion()))
diff --git a/tests/ui/lint/issue-121070-let-range.rs b/tests/ui/lint/issue-121070-let-range.rs
new file mode 100644
index 00000000000..84598dcd258
--- /dev/null
+++ b/tests/ui/lint/issue-121070-let-range.rs
@@ -0,0 +1,16 @@
+// check-pass
+
+#![feature(let_chains)]
+#![allow(irrefutable_let_patterns)]
+fn main() {
+    let _a = 0..1;
+
+    if let x = (0..1) {
+        eprintln!("x: {:?}", x);
+    }
+    if let x = (0..1) &&
+        let _y = (0..2)
+    {
+        eprintln!("x: {:?}", x);
+    }
+}