about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSamuel Tardieu <sam@rfc1149.net>2025-05-28 20:18:22 +0200
committerSamuel Tardieu <sam@rfc1149.net>2025-05-28 20:40:05 +0200
commit3c8bfd144b7b740f7cde10b14ea86fc1dbc7ce63 (patch)
treee51209f893b521744bc4ad4a9baad50f318bfa8b
parentbeaf15532abe888421ad6c6fa127f03a6d800656 (diff)
downloadrust-3c8bfd144b7b740f7cde10b14ea86fc1dbc7ce63.tar.gz
rust-3c8bfd144b7b740f7cde10b14ea86fc1dbc7ce63.zip
`zombie_processes`: do not complain about early early returns
If an early return is found under the HIR local declaration node but
before the child process is created, it should not trigger the lint
because the child process has not yet been created.
-rw-r--r--clippy_lints/src/zombie_processes.rs26
-rw-r--r--tests/ui/zombie_processes.rs10
2 files changed, 21 insertions, 15 deletions
diff --git a/clippy_lints/src/zombie_processes.rs b/clippy_lints/src/zombie_processes.rs
index 09f1084fe70..6ab94a52210 100644
--- a/clippy_lints/src/zombie_processes.rs
+++ b/clippy_lints/src/zombie_processes.rs
@@ -5,7 +5,7 @@ use rustc_ast::Mutability;
 use rustc_ast::visit::visit_opt;
 use rustc_errors::Applicability;
 use rustc_hir::def_id::LocalDefId;
-use rustc_hir::intravisit::{Visitor, walk_block, walk_expr, walk_local};
+use rustc_hir::intravisit::{Visitor, walk_block, walk_expr};
 use rustc_hir::{Expr, ExprKind, HirId, LetStmt, Node, PatKind, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter;
@@ -69,8 +69,9 @@ impl<'tcx> LateLintPass<'tcx> for ZombieProcesses {
                     let mut vis = WaitFinder {
                         cx,
                         local_id,
+                        create_id: expr.hir_id,
                         body_id: cx.tcx.hir_enclosing_body_owner(expr.hir_id),
-                        state: VisitorState::WalkUpToLocal,
+                        state: VisitorState::WalkUpToCreate,
                         early_return: None,
                         missing_wait_branch: None,
                     };
@@ -131,6 +132,7 @@ struct MaybeWait(Span);
 struct WaitFinder<'a, 'tcx> {
     cx: &'a LateContext<'tcx>,
     local_id: HirId,
+    create_id: HirId,
     body_id: LocalDefId,
     state: VisitorState,
     early_return: Option<Span>,
@@ -141,8 +143,8 @@ struct WaitFinder<'a, 'tcx> {
 
 #[derive(PartialEq)]
 enum VisitorState {
-    WalkUpToLocal,
-    LocalFound,
+    WalkUpToCreate,
+    CreateFound,
 }
 
 #[derive(Copy, Clone)]
@@ -155,19 +157,13 @@ impl<'tcx> Visitor<'tcx> for WaitFinder<'_, 'tcx> {
     type NestedFilter = nested_filter::OnlyBodies;
     type Result = ControlFlow<MaybeWait>;
 
-    fn visit_local(&mut self, l: &'tcx LetStmt<'tcx>) -> Self::Result {
-        if self.state == VisitorState::WalkUpToLocal
-            && let PatKind::Binding(_, pat_id, ..) = l.pat.kind
-            && self.local_id == pat_id
-        {
-            self.state = VisitorState::LocalFound;
+    fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) -> Self::Result {
+        if ex.hir_id == self.create_id {
+            self.state = VisitorState::CreateFound;
+            return Continue(());
         }
 
-        walk_local(self, l)
-    }
-
-    fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) -> Self::Result {
-        if self.state != VisitorState::LocalFound {
+        if self.state != VisitorState::CreateFound {
             return walk_expr(self, ex);
         }
 
diff --git a/tests/ui/zombie_processes.rs b/tests/ui/zombie_processes.rs
index 395f9dd2def..e81b5fd4f3e 100644
--- a/tests/ui/zombie_processes.rs
+++ b/tests/ui/zombie_processes.rs
@@ -198,3 +198,13 @@ mod issue14677 {
         child.wait().unwrap();
     }
 }
+
+fn issue14911() -> std::io::Result<String> {
+    let (mut recv, send) = std::io::pipe()?;
+    let mut command = Command::new("ls")
+        .stdout(send.try_clone()?)
+        .spawn()
+        .expect("Could not spawn new process...");
+    command.wait()?;
+    Ok("".into())
+}