about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJason Newcomb <jsnewcomb@pm.me>2025-06-03 13:48:53 +0000
committerGitHub <noreply@github.com>2025-06-03 13:48:53 +0000
commit716eadf674f84ba932a0d3b27c18cd07e9839925 (patch)
treec414b43cdebb3ddf1beaaf6fd9534810cc70ebdc
parent9b8c42cbb1493c5e0c089f73a8a9118a0894d231 (diff)
parent3c8bfd144b7b740f7cde10b14ea86fc1dbc7ce63 (diff)
downloadrust-716eadf674f84ba932a0d3b27c18cd07e9839925.tar.gz
rust-716eadf674f84ba932a0d3b27c18cd07e9839925.zip
`zombie_processes`: do not complain about early early returns (#14912)
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.

changelog: [`zombie_process`]: do not complain about early early returns

Fixes rust-lang/rust-clippy#14911
-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())
+}