Skip to content

Commit e1cbf02

Browse files
committed
Undefined subroutine &%s called, close to label '%s'
#17839 requested a compile-time warning for the situation whereby a single colon is accdentally typed as a package separator when calling a function. For example: ``` package BOOP; sub beep; package main; BOOP:beep(); # Meant to be BOOP::beep(); ``` However, because of both Perl's syntax and the potential to populate the stash at runtime, this falls somewhere between very difficult and impossible. As an alternative, some enhanced fatal error wording was requested and this commit attempts to provide that. The above example would previously die with the message: ``` Undefined subroutine &main::beep called at ... line 4. ``` Now it dies with the message: ``` Undefined subroutine &main::beep called, close to label 'BOOP' at ... line 4. ``` For some of the same reasons mentioned, distinguishing this typo from other errors at runtime - such as the target subroutine not being present at all - is also nigh on impossible. The hope is that the error message will give some additional clue when the error is the result of a typo, without distracting the user in all other cases.
1 parent 6cbecd6 commit e1cbf02

File tree

4 files changed

+39
-0
lines changed

4 files changed

+39
-0
lines changed

pod/perldelta.pod

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,18 @@ and L</New Warnings>
196196

197197
=item *
198198

199+
L<Undefined subroutine &%s called, close to label '%s'|perldiag/"Undefined subroutine &%s called, close to label '%s'">
200+
201+
(F) The subroutine indicated hasn't been defined, or if it was, it has
202+
since been undefined.
203+
204+
This error could also indicate a mistyped package separator, when a
205+
single colon was typed instead of two colons. For example, C<Foo:bar()>
206+
would be parsed as the label C<Foo> followed by an unqualified function
207+
name: C<foo: bar()>.
208+
209+
=item *
210+
199211
XXX L<message|perldiag/"message">
200212

201213
=back

pod/perldiag.pod

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6820,6 +6820,16 @@ Perhaps it's in a different package? See L<perlfunc/sort>.
68206820
(F) The subroutine indicated hasn't been defined, or if it was, it has
68216821
since been undefined.
68226822

6823+
=item Undefined subroutine &%s called, close to label '%s'
6824+
6825+
(F) The subroutine indicated hasn't been defined, or if it was, it has
6826+
since been undefined.
6827+
6828+
This error could also indicate a mistyped package separator, when a
6829+
single colon was typed instead of two colons. For example, C<Foo:bar()>
6830+
would be parsed as the label C<Foo> followed by an unqualified function
6831+
name: C<foo: bar()>.
6832+
68236833
=item Undefined subroutine called
68246834

68256835
(F) The anonymous subroutine you're trying to call hasn't been defined,

pp_hot.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6228,6 +6228,14 @@ S_croak_undefined_subroutine(pTHX_ CV const *cv, GV const *gv)
62286228
SV *sub_name = newSV_type_mortal(SVt_PV);
62296229
gv_efullname3(sub_name, gv, NULL);
62306230

6231+
/* Heuristic to spot BOOP:boop() typo, when the intention was
6232+
* to call BOOP::boop(). */
6233+
const char * label = CopLABEL(PL_curcop);
6234+
if (label && OpSIBLING(PL_curcop) == PL_op) {
6235+
croak("Undefined subroutine &%" SVf " called, close to label '%s'",
6236+
SVfARG(sub_name), label);
6237+
}
6238+
62316239
croak("Undefined subroutine &%" SVf " called", SVfARG(sub_name));
62326240
}
62336241
NOT_REACHED; /* NOTREACHED */

t/lib/croak/pp_hot

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,15 @@ Undefined subroutine &main::foo called at - line 3.
4545
&$foosub;
4646
EXPECT
4747
Undefined subroutine &main::foo called at - line 2.
48+
########
49+
# NAME package separator typo, creating a label by accident
50+
package BEEP;
51+
sub boop;
52+
package main;
53+
BEEP:boop();
54+
EXPECT
55+
Undefined subroutine &main::boop called, close to label 'BEEP' at - line 4.
56+
4857
########
4958
# NAME calling undef scalar
5059
&{+undef};

0 commit comments

Comments
 (0)