Fix zombie_processes FP inside closures (#14696)

Closes rust-lang/rust-clippy#14677

changelog: [`zombie_processes`] fix FP inside closures
This commit is contained in:
Manish Goregaokar 2025-04-28 15:41:40 +00:00 committed by GitHub
commit 549107dbad
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 26 additions and 1 deletions

View file

@ -4,6 +4,7 @@ use clippy_utils::{fn_def_id, get_enclosing_block, path_to_local_id};
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::{Expr, ExprKind, HirId, LetStmt, Node, PatKind, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
@ -68,6 +69,7 @@ impl<'tcx> LateLintPass<'tcx> for ZombieProcesses {
let mut vis = WaitFinder {
cx,
local_id,
body_id: cx.tcx.hir_enclosing_body_owner(expr.hir_id),
state: VisitorState::WalkUpToLocal,
early_return: None,
missing_wait_branch: None,
@ -129,6 +131,7 @@ struct MaybeWait(Span);
struct WaitFinder<'a, 'tcx> {
cx: &'a LateContext<'tcx>,
local_id: HirId,
body_id: LocalDefId,
state: VisitorState,
early_return: Option<Span>,
// When joining two if branches where one of them doesn't call `wait()`, stores its span for more targeted help
@ -186,7 +189,7 @@ impl<'tcx> Visitor<'tcx> for WaitFinder<'_, 'tcx> {
}
} else {
match ex.kind {
ExprKind::Ret(e) => {
ExprKind::Ret(e) if self.cx.tcx.hir_enclosing_body_owner(ex.hir_id) == self.body_id => {
visit_opt!(self, visit_expr, e);
if self.early_return.is_none() {
self.early_return = Some(ex.span);

View file

@ -176,3 +176,25 @@ fn return_wait() -> ExitStatus {
let mut x = Command::new("").spawn().unwrap();
return x.wait().unwrap();
}
mod issue14677 {
use std::io;
use std::process::Command;
fn do_something<F: Fn() -> Result<(), ()>>(f: F) {
todo!()
}
fn foo() {
let mut child = Command::new("true").spawn().unwrap();
let some_condition = true;
do_something(|| {
if some_condition {
return Err(());
}
Ok(())
});
child.kill().unwrap();
child.wait().unwrap();
}
}