about summary refs log tree commit diff
path: root/clippy_utils/src
diff options
context:
space:
mode:
authorJason Newcomb <jsnewcomb@pm.me>2022-06-17 22:21:42 -0400
committerJason Newcomb <jsnewcomb@pm.me>2022-07-07 20:06:36 -0400
commit196174ddad8cac276db8d44c22c7739f614a0fbc (patch)
treeaddd1f8c32d4721b86450f9e7f4b675a505cb737 /clippy_utils/src
parent54feac18d1ad9cc5af1f71dfb34baa32f99630ae (diff)
downloadrust-196174ddad8cac276db8d44c22c7739f614a0fbc.tar.gz
rust-196174ddad8cac276db8d44c22c7739f614a0fbc.zip
Changes to `let_unit_value`
* View through locals in `let_unit_value` when determining if inference is required
* Don't remove typed let bindings for more functions
Diffstat (limited to 'clippy_utils/src')
-rw-r--r--clippy_utils/src/visitors.rs46
1 files changed, 46 insertions, 0 deletions
diff --git a/clippy_utils/src/visitors.rs b/clippy_utils/src/visitors.rs
index 68cfa8c1aa8..e89a46b8538 100644
--- a/clippy_utils/src/visitors.rs
+++ b/clippy_utils/src/visitors.rs
@@ -617,3 +617,49 @@ pub fn any_temporaries_need_ordered_drop<'tcx>(cx: &LateContext<'tcx>, e: &'tcx
     })
     .is_break()
 }
+
+/// Runs the given function for each path expression referencing the given local which occur after
+/// the given expression.
+pub fn for_each_local_assignment<'tcx, B>(
+    cx: &LateContext<'tcx>,
+    local_id: HirId,
+    f: impl FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B>,
+) -> ControlFlow<B> {
+    struct V<'cx, 'tcx, F, B> {
+        cx: &'cx LateContext<'tcx>,
+        local_id: HirId,
+        res: ControlFlow<B>,
+        f: F,
+    }
+    impl<'cx, 'tcx, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B>, B> Visitor<'tcx> for V<'cx, 'tcx, F, B> {
+        type NestedFilter = nested_filter::OnlyBodies;
+        fn nested_visit_map(&mut self) -> Self::Map {
+            self.cx.tcx.hir()
+        }
+
+        fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) {
+            if let ExprKind::Assign(lhs, rhs, _) = e.kind
+                && self.res.is_continue()
+                && path_to_local_id(lhs, self.local_id)
+            {
+                self.res = (self.f)(rhs);
+                self.visit_expr(rhs);
+            } else {
+                walk_expr(self, e);
+            }
+        }
+    }
+
+    if let Some(b) = get_enclosing_block(cx, local_id) {
+        let mut v = V {
+            cx,
+            local_id,
+            res: ControlFlow::Continue(()),
+            f,
+        };
+        v.visit_block(b);
+        v.res
+    } else {
+        ControlFlow::Continue(())
+    }
+}