NAME
Perl::Critic::Policy::ControlStructures::LoopsRequireLabels - Require labels on loops and their break keywords
VERSION
version 0.01
DESCRIPTION
This policy requires loop-control keywords (next, last, redo) and the loops that contain them to carry explicit labels.
Labels make loop-control flow visible at a glance and prevent bugs when nested loops are added, removed, or reordered during refactoring.
EXAMPLES
mode=always
while (1) {
next; # not ok (loop + break both flagged)
}
LOOP:
while (1) {
next LOOP; # ok
}
LOOP:
while (1) {
next; # not ok (break inside labeled loop is bare)
}
while (1) {
next OUTER; # ok (break references a label even if loop lacks one)
}
mode=nested (default, max_lines=5)
while (1) {
next; # ok (top-level, body is 2 lines <= 5)
}
while (1) {
while (1) {
next; # not ok (inner loop is nested)
}
}
while (1) {
INNER:
while (1) {
next; # not ok (inner loop has label but break is bare)
}
}
while (1) {
INNER:
while (1) {
next INNER; # ok (inner loop labeled, break references it)
}
}
while (1) { # not ok (top-level but body is 6 lines > 5)
print "a";
print "b";
print "c";
next;
}
mode=max_lines, max_lines=3
while (1) {
next; # ok (body is 2 lines <= 3)
}
while (1) { # not ok (body is 4 lines > 3)
next;
last;
}
while (1) { # ok (body is 5 lines but no break keywords)
print "hello";
print "world";
}
Cascading labels through ancestor loops (non-configurable)
Regardless of the active mode, a bare break keyword is always flagged when any ancestor loop carries a label. This prevents ambiguity about which loop the keyword targets.
OUTER:
while (1) {
while (1) { # no label
next; # not ok (nearest loop unlabeled AND
# OUTER has a label)
}
}
OUTER:
while (1) {
next OUTER; # ok (break in outer references its label)
last; # not ok (outer has label but break is bare)
INNER:
while (1) {
last OUTER; # ok (break references an outer label)
}
}
continue blocks attached to a loop are treated as part of that loop for the purposes of this policy. Break keywords inside continue are subject to the same labeling rules as those in the main body.
Note that the max_lines line count considers only the main body block (from { to }). A long continue block does not by itself trigger the line-count threshold; only nesting or break keywords in the main body can do that.
while (1) {
# no break keywords in the body
} continue {
next; # not ok (same rules apply here)
}
LOOP:
while (1) {
} continue {
next LOOP; # ok (break references the loop's label)
last LOOP; # ok
}
CONFIGURATION
Three modes control when labels are required:
always-
Any loop that contains a
next,last, orredokeyword must have a label, and those keywords must reference a label. Themax_linessetting has no effect in this mode. nested(default)-
Labels are required when the loop is nested inside another real loop (
for,foreach,while, oruntil). Additionally, regardless of nesting, labels are required if the loop body spans more thanmax_linessource lines (counting from{to}inclusive of the body block only; any attachedcontinueblock is not counted). This makesmax_linesact as a safety net for long top-level loops. Setmax_linesto a high value (e.g. 1000) to effectively disable the line-count check and rely on nesting alone. max_lines-
Labels are required when the loop body spans more than
max_linessource lines (counting from{to}inclusive of the body block only; any attachedcontinueblock is not counted). Nesting is not considered. The threshold is configured with themax_linesparameter (default 30).
Example perlcriticrc:
# Built-in defaults (mode=nested, max_lines=30)
[ControlStructures::LoopsRequireLabels]
# Same defaults, written explicitly (default configuration)
[ControlStructures::LoopsRequireLabels]
mode = nested
max_lines = 30
# Flag all loops with break keywords
[ControlStructures::LoopsRequireLabels]
mode = always
# Flag only by length, ignore nesting
[ControlStructures::LoopsRequireLabels]
mode = max_lines
max_lines = 80
SEE ALSO
Perl::Critic, "last" in perlfunc, "next" in perlfunc, "redo" in perlfunc
AUTHOR
Dean Hamstead <dean@fragfest.com.au>
COPYRIGHT AND LICENSE
This software is Copyright (c) 2026 by Dean Hamstead.
This is free software, licensed under:
The MIT (X11) License