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:
check_unreachable_codedispatches on the root, then callsvisit_nodefor each statement in top-level lists.check_statement_listiterates a&[Node]linearly. When an unconditional exit is found, all subsequent siblings get a PL406 diagnostic. Nested blocks are recursed into freshly.- Subroutine and method bodies (
Subroutine,Method) trigger a fresh call tovisit_node, so areturnin an inner sub never affects the outer statement list. eval { }blocks are intentionally not recursed into:dieinsideeval { }is caught and does not exit the outer scope.
§Scope of detection
| Unconditional exit | Detected? |
|---|---|
return | Yes |
die "msg" | Yes (direct FunctionCall at statement level) |
exit $code | Yes |
croak "msg" | Yes |
Carp::croak "msg" | Yes |
confess "msg" | Yes |
Carp::confess "msg" | Yes |
last in loop body | Yes |
next in loop body | Yes |
redo in loop body | Yes |
return if $cond | No (conditional via StatementModifier) |
die inside or | No (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.