NAME
Perl::Critic::Policy::ControlStructures::ProhibitBareBlockLoopControls - Prohibit unlabeled loop controls in non-loop blocks
VERSION
version 0.05
DESCRIPTION
This policy flags next, last, and redo when used inside blocks that are not real loops or where control flow is confusing (bare {} blocks, do {} blocks, anonymous subroutines, eval {}, map/grep).
Why these blocks are problematic:
Bare
{}blocks are loops that execute once, sonextandlastboth exit the block;nextadditionally runs any attachedcontinueblock.do {}blocks are not loops -- control keywords target the nearest enclosing real loop instead of thedoblock itself.Anonymous subroutines
sub {}andeval {}are not loops either.map {}/grep {}blocks are expression blocks -- loop controls do not behave as expected.
The default policy depends on both the keyword and the enclosing block type:
Keyword bare C<{}> C<do {}>
------------------------------------------------
last require_label forbid
next forbid forbid
redo forbid forbid
EXAMPLES
The following examples illustrate the default configuration.
Bare blocks ({ })
{
next; # not ok
}
FOO: {
next FOO; # not ok
}
{
last; # not ok
}
BAR: {
last BAR; # ok
}
{
redo; # not ok
}
BAZ: {
redo BAZ; # not ok
}
Bare blocks inside real loops
for my $x (@items) {
{
next; # not ok
}
}
for my $x (@items) {
FOO: {
next FOO; # not ok
}
}
BAR:
for my $x (@items) {
{
next BAR; # ok (targets the outer real loop)
}
}
do { } blocks
do {
next; # not ok
};
do {
last LOOP; # not ok (label does not help -- do is not a loop)
};
Anonymous subroutines (sub { })
sub {
next; # not ok
};
sub {
last LABEL; # ok (if called from within a matching loop)
};
eval { } blocks
eval {
last; # not ok
};
map and grep blocks
map { next; } @list; # not ok
grep { redo; } @list; # not ok
Real loops (always safe)
while (1) {
next; # ok
}
for my $x (@items) {
last if $x eq 'foo'; # ok
}
foreach my $k (keys %h) {
next; # ok
}
CONFIGURATION
Each keyword next, last, redo can be set to one of:
forbid-- always flag this keyword in non-loop blocks (default fornextandredo)require_label-- flag unless the keyword has an explicit label (default forlast)allow-- do not check this keyword at all in non-loop blocks-
These per-keyword defaults apply when no block-type override is in effect (or the override is set to
follow; see below).
Block-type overrides (do_block, bare_block) can modify the behaviour for specific block types:
bare_block:forbid,require_label, orfollow(default) per-keyword settingsdo_block:forbid(default),require_label, orfollowper-keyword settings
Bare blocks are real loops (they execute once), so labeled controls work correctly. The default is follow, which defers to the per-keyword setting for each keyword: last requires a label, next and redo are always flagged. do blocks are not loops at all, so controls are forbidden entirely by default; require_label allows them when an outer loop is the intended target.
Example perlcriticrc:
[ControlStructures::ProhibitBareBlockLoopControls]
next = forbid
last = require_label
redo = forbid
do_block = forbid
bare_block = follow
Note: This is the default configuration.
SEE ALSO
"last" in perlfunc, "next" in perlfunc, "redo" in perlfunc, Perl::Critic::Policy::ControlStructures::ProhibitReturnInDoBlock
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