about summary refs log tree commit diff
path: root/clippy_utils/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-04-15 01:57:52 +0000
committerbors <bors@rust-lang.org>2022-04-15 01:57:52 +0000
commit0bc93b67f55ed04de7b462af69f06407844c6531 (patch)
tree1544ba68bd9a4a11f91b8a64e592ef71d09999a1 /clippy_utils/src
parent80bcd9bc6e91cc00fbf7c9bf7aab13c0a4ec2367 (diff)
parent70f7c624e442c3049d440cd20f8d77b66580105c (diff)
downloadrust-0bc93b67f55ed04de7b462af69f06407844c6531.tar.gz
rust-0bc93b67f55ed04de7b462af69f06407844c6531.zip
Auto merge of #8563 - Jarcho:let_unit_1502, r=Jarcho
Don't lint `let_unit_value` when needed for type inferenece

fixes: #1502

Pinging `@dtolnay.` I think this is enough to fix the issue. Do you have a good list crates to test this on?

changelog: Don't lint `let_unit_value` when needed for type inference
Diffstat (limited to 'clippy_utils/src')
-rw-r--r--clippy_utils/src/visitors.rs34
1 files changed, 34 insertions, 0 deletions
diff --git a/clippy_utils/src/visitors.rs b/clippy_utils/src/visitors.rs
index 3db64b25353..c00bc2bd213 100644
--- a/clippy_utils/src/visitors.rs
+++ b/clippy_utils/src/visitors.rs
@@ -1,4 +1,5 @@
 use crate::path_to_local_id;
+use core::ops::ControlFlow;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::{self, walk_block, walk_expr, Visitor};
@@ -402,3 +403,36 @@ pub fn contains_unsafe_block<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>)
     v.visit_expr(e);
     v.found_unsafe
 }
+
+/// Runs the given function for each sub-expression producing the final value consumed by the parent
+/// of the give expression.
+///
+/// e.g. for the following expression
+/// ```rust,ignore
+/// if foo {
+///     f(0)
+/// } else {
+///     1 + 1
+/// }
+/// ```
+/// this will pass both `f(0)` and `1+1` to the given function.
+pub fn for_each_value_source<'tcx, B>(
+    e: &'tcx Expr<'tcx>,
+    f: &mut impl FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B>,
+) -> ControlFlow<B> {
+    match e.kind {
+        ExprKind::Block(Block { expr: Some(e), .. }, _) => for_each_value_source(e, f),
+        ExprKind::Match(_, arms, _) => {
+            for arm in arms {
+                for_each_value_source(arm.body, f)?;
+            }
+            ControlFlow::Continue(())
+        },
+        ExprKind::If(_, if_expr, Some(else_expr)) => {
+            for_each_value_source(if_expr, f)?;
+            for_each_value_source(else_expr, f)
+        },
+        ExprKind::DropTemps(e) => for_each_value_source(e, f),
+        _ => f(e),
+    }
+}