about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/matches.rs26
-rw-r--r--tests/ui/match_single_binding.fixed10
-rw-r--r--tests/ui/match_single_binding.rs9
-rw-r--r--tests/ui/match_single_binding.stderr19
4 files changed, 57 insertions, 7 deletions
diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs
index b0aae5e30e6..40880f78270 100644
--- a/clippy_lints/src/matches.rs
+++ b/clippy_lints/src/matches.rs
@@ -3,9 +3,10 @@ use crate::utils::paths;
 use crate::utils::sugg::Sugg;
 use crate::utils::usage::is_unused;
 use crate::utils::{
-    expr_block, get_arg_name, in_macro, indent_of, is_allowed, is_expn_of, is_refutable, is_wild, match_qpath,
-    match_type, match_var, multispan_sugg, remove_blocks, snippet, snippet_block, snippet_with_applicability,
-    span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then, walk_ptrs_ty,
+    expr_block, get_arg_name, get_parent_expr, in_macro, indent_of, is_allowed, is_expn_of, is_refutable, is_wild,
+    match_qpath, match_type, match_var, multispan_sugg, remove_blocks, snippet, snippet_block,
+    snippet_with_applicability, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then,
+    walk_ptrs_ty,
 };
 use if_chain::if_chain;
 use rustc::lint::in_external_macro;
@@ -928,14 +929,27 @@ fn check_match_single_binding<'a>(cx: &LateContext<'_, 'a>, ex: &Expr<'a>, arms:
                     ),
                 )
             } else {
+                // If we are in closure, we need curly braces around suggestion
+                let mut indent = " ".repeat(indent_of(cx, ex.span).unwrap_or(0));
+                let (mut cbrace_start, mut cbrace_end) = ("".to_string(), "".to_string());
+                if let Some(parent_expr) = get_parent_expr(cx, expr) {
+                    if let ExprKind::Closure(..) = parent_expr.kind {
+                        cbrace_end = format!("\n{}}}", indent);
+                        // Fix body indent due to the closure
+                        indent = " ".repeat(indent_of(cx, bind_names).unwrap_or(0));
+                        cbrace_start = format!("{{\n{}", indent);
+                    }
+                };
                 (
                     expr.span,
                     format!(
-                        "let {} = {};\n{}{}",
+                        "{}let {} = {};\n{}{}{}",
+                        cbrace_start,
                         snippet_with_applicability(cx, bind_names, "..", &mut applicability),
                         snippet_with_applicability(cx, matched_vars, "..", &mut applicability),
-                        " ".repeat(indent_of(cx, expr.span).unwrap_or(0)),
-                        snippet_body
+                        indent,
+                        snippet_body,
+                        cbrace_end
                     ),
                 )
             };
diff --git a/tests/ui/match_single_binding.fixed b/tests/ui/match_single_binding.fixed
index bc2346a8dbf..90f00aa7871 100644
--- a/tests/ui/match_single_binding.fixed
+++ b/tests/ui/match_single_binding.fixed
@@ -67,4 +67,14 @@ fn main() {
     // Lint
     let Point { x, y } = coords();
     let product = x * y;
+    // Lint
+    let v = vec![Some(1), Some(2), Some(3), Some(4)];
+    #[allow(clippy::let_and_return)]
+    let _ = v
+        .iter()
+        .map(|i| {
+            let unwrapped = i.unwrap();
+            unwrapped
+        })
+        .collect::<Vec<u8>>();
 }
diff --git a/tests/ui/match_single_binding.rs b/tests/ui/match_single_binding.rs
index 0517b3bbfbf..4a4b290036c 100644
--- a/tests/ui/match_single_binding.rs
+++ b/tests/ui/match_single_binding.rs
@@ -80,4 +80,13 @@ fn main() {
     let product = match coords() {
         Point { x, y } => x * y,
     };
+    // Lint
+    let v = vec![Some(1), Some(2), Some(3), Some(4)];
+    #[allow(clippy::let_and_return)]
+    let _ = v
+        .iter()
+        .map(|i| match i.unwrap() {
+            unwrapped => unwrapped,
+        })
+        .collect::<Vec<u8>>();
 }
diff --git a/tests/ui/match_single_binding.stderr b/tests/ui/match_single_binding.stderr
index 05ba9e5f7f3..cf741a989c2 100644
--- a/tests/ui/match_single_binding.stderr
+++ b/tests/ui/match_single_binding.stderr
@@ -150,5 +150,22 @@ LL |     let Point { x, y } = coords();
 LL |     let product = x * y;
    |
 
-error: aborting due to 10 previous errors
+error: this match could be written as a `let` statement
+  --> $DIR/match_single_binding.rs:88:18
+   |
+LL |           .map(|i| match i.unwrap() {
+   |  __________________^
+LL | |             unwrapped => unwrapped,
+LL | |         })
+   | |_________^
+   |
+help: consider using `let` statement
+   |
+LL |         .map(|i| {
+LL |             let unwrapped = i.unwrap();
+LL |             unwrapped
+LL |         })
+   |
+
+error: aborting due to 11 previous errors