about summary refs log tree commit diff
path: root/clippy_lints/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-04-17 19:29:17 +0000
committerbors <bors@rust-lang.org>2020-04-17 19:29:17 +0000
commit1c0e4e5b97f05d6f397bf941b16e1e826310a5ed (patch)
tree9df787098257f40a3749a33a856a891ed209004b /clippy_lints/src
parentf1fb815603e05a6c48f53e18a16e4804dface48a (diff)
parent092c4595fef374cc10cc44ada67a14e773f1b49e (diff)
Auto merge of #5483 - alex-700:fix-redundant-pattern-matching, r=flip1995
fix redundant_pattern_matching lint

- now it handles `while let` case  (related to #5462)
- better suggestions in `if let` case

changelog: Fix suggestion in `redundant_pattern_matching` and also apply this lint to the `while let` case
Diffstat (limited to 'clippy_lints/src')
-rw-r--r--clippy_lints/src/redundant_pattern_matching.rs30
1 files changed, 21 insertions, 9 deletions
diff --git a/clippy_lints/src/redundant_pattern_matching.rs b/clippy_lints/src/redundant_pattern_matching.rs
index bdc32dbba87..334ceed64c2 100644
--- a/clippy_lints/src/redundant_pattern_matching.rs
+++ b/clippy_lints/src/redundant_pattern_matching.rs
@@ -1,4 +1,5 @@
-use crate::utils::{match_qpath, paths, snippet, span_lint_and_then};
+use crate::utils::{match_qpath, match_trait_method, paths, snippet, span_lint_and_then};
+use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{Arm, Expr, ExprKind, MatchSource, PatKind, QPath};
@@ -48,9 +49,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantPatternMatching {
         if let ExprKind::Match(op, arms, ref match_source) = &expr.kind {
             match match_source {
                 MatchSource::Normal => find_sugg_for_match(cx, expr, op, arms),
-                MatchSource::IfLetDesugar { contains_else_clause } => {
-                    find_sugg_for_if_let(cx, expr, op, arms, *contains_else_clause)
-                },
+                MatchSource::IfLetDesugar { .. } => find_sugg_for_if_let(cx, expr, op, arms, "if"),
+                MatchSource::WhileLetDesugar => find_sugg_for_if_let(cx, expr, op, arms, "while"),
                 _ => return,
             }
         }
@@ -62,7 +62,7 @@ fn find_sugg_for_if_let<'a, 'tcx>(
     expr: &'tcx Expr<'_>,
     op: &Expr<'_>,
     arms: &[Arm<'_>],
-    has_else: bool,
+    keyword: &'static str,
 ) {
     let good_method = match arms[0].pat.kind {
         PatKind::TupleStruct(ref path, ref patterns, _) if patterns.len() == 1 => {
@@ -86,7 +86,16 @@ fn find_sugg_for_if_let<'a, 'tcx>(
         _ => return,
     };
 
-    let maybe_semi = if has_else { "" } else { ";" };
+    // check that `while_let_on_iterator` lint does not trigger
+    if_chain! {
+        if keyword == "while";
+        if let ExprKind::MethodCall(method_path, _, _) = op.kind;
+        if method_path.ident.name == sym!(next);
+        if match_trait_method(cx, op, &paths::ITERATOR);
+        then {
+            return;
+        }
+    }
 
     span_lint_and_then(
         cx,
@@ -94,12 +103,15 @@ fn find_sugg_for_if_let<'a, 'tcx>(
         arms[0].pat.span,
         &format!("redundant pattern matching, consider using `{}`", good_method),
         |diag| {
-            let span = expr.span.to(op.span);
+            // in the case of WhileLetDesugar expr.span == op.span incorrectly.
+            // this is a workaround to restore true value of expr.span
+            let expr_span = expr.span.to(arms[1].span);
+            let span = expr_span.until(op.span.shrink_to_hi());
             diag.span_suggestion(
                 span,
                 "try this",
-                format!("{}.{}{}", snippet(cx, op.span, "_"), good_method, maybe_semi),
-                Applicability::MaybeIncorrect, // snippet
+                format!("{} {}.{}", keyword, snippet(cx, op.span, "_"), good_method),
+                Applicability::MachineApplicable, // snippet
             );
         },
     );