]> git.lizzy.rs Git - rust.git/blobdiff - src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
Merge branch 'master' of http://localhost:8000/rust-lang/rust.git:at_commit=75dd959a3...
[rust.git] / src / tools / clippy / clippy_lints / src / operators / assign_op_pattern.rs
index 945a09a647c415fc2cd2902cd053fc6a42e8fc5d..ee9fd94064c08a53d7d7c4f402ac3db43dd11389 100644 (file)
@@ -2,16 +2,17 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::implements_trait;
+use clippy_utils::visitors::for_each_expr;
 use clippy_utils::{eq_expr_value, trait_ref_of_method};
+use core::ops::ControlFlow;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 use rustc_lint::LateContext;
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty::BorrowKind;
 use rustc_trait_selection::infer::TyCtxtInferExt;
-use rustc_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 
 use super::ASSIGN_OP_PATTERN;
 
@@ -28,7 +29,7 @@ pub(super) fn check<'tcx>(
             if_chain! {
                 if let Some((_, lang_item)) = binop_traits(op.node);
                 if let Ok(trait_id) = cx.tcx.lang_items().require(lang_item);
-                let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id);
+                let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id).def_id;
                 if trait_ref_of_method(cx, parent_fn)
                     .map_or(true, |t| t.path.res.def_id() != trait_id);
                 if implements_trait(cx, ty, trait_id, &[rty.into()]);
@@ -55,7 +56,7 @@ pub(super) fn check<'tcx>(
                                 diag.span_suggestion(
                                     expr.span,
                                     "replace it with",
-                                    format!("{} {}= {}", snip_a, op.node.as_str(), snip_r),
+                                    format!("{snip_a} {}= {snip_r}", op.node.as_str()),
                                     Applicability::MachineApplicable,
                                 );
                             }
@@ -65,15 +66,19 @@ pub(super) fn check<'tcx>(
             }
         };
 
-        let mut visitor = ExprVisitor {
-            assignee,
-            counter: 0,
-            cx,
-        };
-
-        walk_expr(&mut visitor, e);
+        let mut found = false;
+        let found_multiple = for_each_expr(e, |e| {
+            if eq_expr_value(cx, assignee, e) {
+                if found {
+                    return ControlFlow::Break(());
+                }
+                found = true;
+            }
+            ControlFlow::Continue(())
+        })
+        .is_some();
 
-        if visitor.counter == 1 {
+        if found && !found_multiple {
             // a = a op b
             if eq_expr_value(cx, assignee, l) {
                 lint(assignee, r);
@@ -98,22 +103,6 @@ pub(super) fn check<'tcx>(
     }
 }
 
-struct ExprVisitor<'a, 'tcx> {
-    assignee: &'a hir::Expr<'a>,
-    counter: u8,
-    cx: &'a LateContext<'tcx>,
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for ExprVisitor<'a, 'tcx> {
-    fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
-        if eq_expr_value(self.cx, self.assignee, expr) {
-            self.counter += 1;
-        }
-
-        walk_expr(self, expr);
-    }
-}
-
 fn imm_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> hir::HirIdSet {
     struct S(hir::HirIdSet);
     impl Delegate<'_> for S {
@@ -134,16 +123,15 @@ fn copy(&mut self, _: &PlaceWithHirId<'_>, _: hir::HirId) {}
     }
 
     let mut s = S(hir::HirIdSet::default());
-    cx.tcx.infer_ctxt().enter(|infcx| {
-        let mut v = ExprUseVisitor::new(
-            &mut s,
-            &infcx,
-            cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap()),
-            cx.param_env,
-            cx.typeck_results(),
-        );
-        v.consume_expr(e);
-    });
+    let infcx = cx.tcx.infer_ctxt().build();
+    let mut v = ExprUseVisitor::new(
+        &mut s,
+        &infcx,
+        cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap()),
+        cx.param_env,
+        cx.typeck_results(),
+    );
+    v.consume_expr(e);
     s.0
 }
 
@@ -167,15 +155,14 @@ fn copy(&mut self, _: &PlaceWithHirId<'_>, _: hir::HirId) {}
     }
 
     let mut s = S(hir::HirIdSet::default());
-    cx.tcx.infer_ctxt().enter(|infcx| {
-        let mut v = ExprUseVisitor::new(
-            &mut s,
-            &infcx,
-            cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap()),
-            cx.param_env,
-            cx.typeck_results(),
-        );
-        v.consume_expr(e);
-    });
+    let infcx = cx.tcx.infer_ctxt().build();
+    let mut v = ExprUseVisitor::new(
+        &mut s,
+        &infcx,
+        cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap()),
+        cx.param_env,
+        cx.typeck_results(),
+    );
+    v.consume_expr(e);
     s.0
 }