Skip to main content

Module unreachable_code

Module unreachable_code 

Source
Expand description

Unreachable code detection (PL406) Unreachable code detection (PL406)

Identifies statements that cannot execute because they follow an unconditional control-flow exit (return, die, exit, croak, confess, last, next, redo).

§Algorithm

The lint uses recursive statement-slice analysis rather than a flat pre-order AST walk. This is the only correct approach: a pre-order visitor with a reachable: bool flag cannot distinguish “visiting a child of this node” from “visiting the next sibling”, so a return inside a nested subroutine body would incorrectly poison sibling statements in the outer scope.

The correct algorithm:

  1. check_unreachable_code dispatches on the root, then calls visit_node for each statement in top-level lists.
  2. check_statement_list iterates a &[Node] linearly. When an unconditional exit is found, all subsequent siblings get a PL406 diagnostic. Nested blocks are recursed into freshly.
  3. Subroutine and method bodies (Subroutine, Method) trigger a fresh call to visit_node, so a return in an inner sub never affects the outer statement list.
  4. eval { } blocks are intentionally not recursed into: die inside eval { } is caught and does not exit the outer scope.

§Scope of detection

Unconditional exitDetected?
returnYes
die "msg"Yes (direct FunctionCall at statement level)
exit $codeYes
croak "msg"Yes
Carp::croak "msg"Yes
confess "msg"Yes
Carp::confess "msg"Yes
last in loop bodyYes
next in loop bodyYes
redo in loop bodyYes
return if $condNo (conditional via StatementModifier)
die inside orNo (right operand of Binary, not a direct statement)
die inside eval { }No (caught by eval)

Functions§

check_unreachable_code
Entry point for unreachable code detection.