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.
This commit is contained in:
Samuel Tardieu 2025-05-28 20:18:22 +02:00
parent beaf15532a
commit 3c8bfd144b
No known key found for this signature in database
GPG key ID: BDDC3208C6FEAFA8
2 changed files with 21 additions and 15 deletions

View file

@ -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);
}

View file

@ -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())
}