about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/manual_let_else.rs26
-rw-r--r--tests/ui/manual_let_else.rs14
-rw-r--r--tests/ui/manual_let_else.stderr11
3 files changed, 36 insertions, 15 deletions
diff --git a/clippy_lints/src/manual_let_else.rs b/clippy_lints/src/manual_let_else.rs
index 20f06830952..874d36ca9f4 100644
--- a/clippy_lints/src/manual_let_else.rs
+++ b/clippy_lints/src/manual_let_else.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::higher::IfLetOrMatch;
 use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::peel_blocks;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::snippet_with_context;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::visitors::{for_each_expr, Descend};
 use if_chain::if_chain;
@@ -141,20 +141,18 @@ fn emit_manual_let_else(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, pat:
             // * unused binding collision detection with existing ones
             // * putting patterns with at the top level | inside ()
             // for this to be machine applicable.
-            let app = Applicability::HasPlaceholders;
+            let mut app = Applicability::HasPlaceholders;
+            let (sn_pat, _) = snippet_with_context(cx, pat.span, span.ctxt(), "", &mut app);
+            let (sn_expr, _) = snippet_with_context(cx, expr.span, span.ctxt(), "", &mut app);
+            let (sn_else, _) = snippet_with_context(cx, else_body.span, span.ctxt(), "", &mut app);
 
-            if let Some(sn_pat) = snippet_opt(cx, pat.span) &&
-                let Some(sn_expr) = snippet_opt(cx, expr.span) &&
-                let Some(sn_else) = snippet_opt(cx, else_body.span)
-            {
-                let else_bl = if matches!(else_body.kind, ExprKind::Block(..)) {
-                    sn_else
-                } else {
-                    format!("{{ {sn_else} }}")
-                };
-                let sugg = format!("let {sn_pat} = {sn_expr} else {else_bl};");
-                diag.span_suggestion(span, "consider writing", sugg, app);
-            }
+            let else_bl = if matches!(else_body.kind, ExprKind::Block(..)) {
+                sn_else.into_owned()
+            } else {
+                format!("{{ {sn_else} }}")
+            };
+            let sugg = format!("let {sn_pat} = {sn_expr} else {else_bl};");
+            diag.span_suggestion(span, "consider writing", sugg, app);
         },
     );
 }
diff --git a/tests/ui/manual_let_else.rs b/tests/ui/manual_let_else.rs
index 2ef40e5911a..48a162c1360 100644
--- a/tests/ui/manual_let_else.rs
+++ b/tests/ui/manual_let_else.rs
@@ -234,4 +234,18 @@ fn not_fire() {
     // If a type annotation is present, don't lint as
     // expressing the type might be too hard
     let v: () = if let Some(v_some) = g() { v_some } else { panic!() };
+
+    // Issue 9940
+    // Suggestion should not expand macros
+    macro_rules! macro_call {
+        () => {
+            return ()
+        };
+    }
+
+    let ff = Some(1);
+    let _ = match ff {
+        Some(value) => value,
+        _ => macro_call!(),
+    };
 }
diff --git a/tests/ui/manual_let_else.stderr b/tests/ui/manual_let_else.stderr
index 453b68b8bd0..52aac6bc673 100644
--- a/tests/ui/manual_let_else.stderr
+++ b/tests/ui/manual_let_else.stderr
@@ -259,5 +259,14 @@ LL |     create_binding_if_some!(w, g());
    |
    = note: this error originates in the macro `create_binding_if_some` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 17 previous errors
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:247:5
+   |
+LL | /     let _ = match ff {
+LL | |         Some(value) => value,
+LL | |         _ => macro_call!(),
+LL | |     };
+   | |______^ help: consider writing: `let Some(value) = ff else { macro_call!() };`
+
+error: aborting due to 18 previous errors