about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJason Newcomb <jsnewcomb@pm.me>2025-04-17 14:58:53 +0000
committerGitHub <noreply@github.com>2025-04-17 14:58:53 +0000
commit26f43ff346e911d8c5fc66e0fd9e2058ef82ca6e (patch)
tree9dc835fac81ed19395d3bedee49c0a3b43266c51
parenta49ea2d63d03e485eaf5fa1b7dcdbaca162427c7 (diff)
parent10a83274e2d0c7538a1d2073077d713cfcb7f8a9 (diff)
downloadrust-26f43ff346e911d8c5fc66e0fd9e2058ef82ca6e.tar.gz
rust-26f43ff346e911d8c5fc66e0fd9e2058ef82ca6e.zip
`match_single_binding`: allow macros in scrutinee and patterns (#14635)
changelog: [`match_single_binding`]: allow macros in scrutinee and
patterns

Fixes rust-lang/rust-clippy#14634
-rw-r--r--clippy_lints/src/matches/match_single_binding.rs31
-rw-r--r--tests/ui/match_single_binding.fixed17
-rw-r--r--tests/ui/match_single_binding.rs20
-rw-r--r--tests/ui/match_single_binding.stderr44
4 files changed, 94 insertions, 18 deletions
diff --git a/clippy_lints/src/matches/match_single_binding.rs b/clippy_lints/src/matches/match_single_binding.rs
index bca41956f1c..adda3586990 100644
--- a/clippy_lints/src/matches/match_single_binding.rs
+++ b/clippy_lints/src/matches/match_single_binding.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::macros::HirNode;
-use clippy_utils::source::{indent_of, snippet, snippet_block_with_context, snippet_with_applicability};
+use clippy_utils::source::{indent_of, snippet, snippet_block_with_context, snippet_with_context};
 use clippy_utils::{get_parent_expr, is_refutable, peel_blocks};
 use rustc_errors::Applicability;
 use rustc_hir::{Arm, Expr, ExprKind, Node, PatKind, StmtKind};
@@ -24,16 +24,10 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
     let bind_names = arms[0].pat.span;
     let match_body = peel_blocks(arms[0].body);
     let mut app = Applicability::MaybeIncorrect;
-    let mut snippet_body = snippet_block_with_context(
-        cx,
-        match_body.span,
-        arms[0].span.ctxt(),
-        "..",
-        Some(expr.span),
-        &mut app,
-    )
-    .0
-    .to_string();
+    let ctxt = expr.span.ctxt();
+    let mut snippet_body = snippet_block_with_context(cx, match_body.span, ctxt, "..", Some(expr.span), &mut app)
+        .0
+        .to_string();
 
     // Do we need to add ';' to suggestion ?
     if let Node::Stmt(stmt) = cx.tcx.parent_hir_node(expr.hir_id)
@@ -77,10 +71,10 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
                     span,
                     format!(
                         "let {} = {};\n{}let {} = {snippet_body};",
-                        snippet_with_applicability(cx, bind_names, "..", &mut app),
-                        snippet_with_applicability(cx, matched_vars, "..", &mut app),
+                        snippet_with_context(cx, bind_names, ctxt, "..", &mut app).0,
+                        snippet_with_context(cx, matched_vars, ctxt, "..", &mut app).0,
                         " ".repeat(indent_of(cx, expr.span).unwrap_or(0)),
-                        snippet_with_applicability(cx, pat_span, "..", &mut app)
+                        snippet_with_context(cx, pat_span, ctxt, "..", &mut app).0
                     ),
                 ),
                 None => {
@@ -204,14 +198,17 @@ fn sugg_with_curlies<'a>(
         s
     });
 
+    let ctxt = match_expr.span.ctxt();
     let scrutinee = if needs_var_binding {
         format!(
             "let {} = {}",
-            snippet_with_applicability(cx, bind_names, "..", applicability),
-            snippet_with_applicability(cx, matched_vars, "..", applicability)
+            snippet_with_context(cx, bind_names, ctxt, "..", applicability).0,
+            snippet_with_context(cx, matched_vars, ctxt, "..", applicability).0
         )
     } else {
-        snippet_with_applicability(cx, matched_vars, "..", applicability).to_string()
+        snippet_with_context(cx, matched_vars, ctxt, "..", applicability)
+            .0
+            .to_string()
     };
 
     format!("{cbrace_start}{scrutinee};\n{indent}{assignment_str}{snippet_body}{cbrace_end}")
diff --git a/tests/ui/match_single_binding.fixed b/tests/ui/match_single_binding.fixed
index 3a3eee4c958..bdf39796ebf 100644
--- a/tests/ui/match_single_binding.fixed
+++ b/tests/ui/match_single_binding.fixed
@@ -171,3 +171,20 @@ fn issue_10447() -> usize {
 
     2
 }
+
+fn issue14634() {
+    macro_rules! id {
+        ($i:ident) => {
+            $i
+        };
+    }
+    dbg!(3);
+    println!("here");
+    //~^^^ match_single_binding
+    let id!(a) = dbg!(3);
+    println!("found {a}");
+    //~^^^ match_single_binding
+    let id!(b) = dbg!(3);
+    let id!(_a) = dbg!(b + 1);
+    //~^^^ match_single_binding
+}
diff --git a/tests/ui/match_single_binding.rs b/tests/ui/match_single_binding.rs
index ada51254c6c..419ff95d873 100644
--- a/tests/ui/match_single_binding.rs
+++ b/tests/ui/match_single_binding.rs
@@ -229,3 +229,23 @@ fn issue_10447() -> usize {
 
     2
 }
+
+fn issue14634() {
+    macro_rules! id {
+        ($i:ident) => {
+            $i
+        };
+    }
+    match dbg!(3) {
+        _ => println!("here"),
+    }
+    //~^^^ match_single_binding
+    match dbg!(3) {
+        id!(a) => println!("found {a}"),
+    }
+    //~^^^ match_single_binding
+    let id!(_a) = match dbg!(3) {
+        id!(b) => dbg!(b + 1),
+    };
+    //~^^^ match_single_binding
+}
diff --git a/tests/ui/match_single_binding.stderr b/tests/ui/match_single_binding.stderr
index 7e1ec32dac2..bdd0134a5f1 100644
--- a/tests/ui/match_single_binding.stderr
+++ b/tests/ui/match_single_binding.stderr
@@ -336,5 +336,47 @@ LL | |             _ => println!("1"),
 LL | |         },
    | |_________^ help: consider using the match body instead: `println!("1")`
 
-error: aborting due to 24 previous errors
+error: this match could be replaced by its scrutinee and body
+  --> tests/ui/match_single_binding.rs:239:5
+   |
+LL | /     match dbg!(3) {
+LL | |         _ => println!("here"),
+LL | |     }
+   | |_____^
+   |
+help: consider using the scrutinee and body instead
+   |
+LL ~     dbg!(3);
+LL +     println!("here");
+   |
+
+error: this match could be written as a `let` statement
+  --> tests/ui/match_single_binding.rs:243:5
+   |
+LL | /     match dbg!(3) {
+LL | |         id!(a) => println!("found {a}"),
+LL | |     }
+   | |_____^
+   |
+help: consider using a `let` statement
+   |
+LL ~     let id!(a) = dbg!(3);
+LL +     println!("found {a}");
+   |
+
+error: this match could be written as a `let` statement
+  --> tests/ui/match_single_binding.rs:247:5
+   |
+LL | /     let id!(_a) = match dbg!(3) {
+LL | |         id!(b) => dbg!(b + 1),
+LL | |     };
+   | |______^
+   |
+help: consider using a `let` statement
+   |
+LL ~     let id!(b) = dbg!(3);
+LL +     let id!(_a) = dbg!(b + 1);
+   |
+
+error: aborting due to 27 previous errors