This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
‘Subroutine "&x" is not available’ during compilation
authorFather Chrysostomos <sprout@cpan.org>
Thu, 6 Sep 2012 23:03:20 +0000 (16:03 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Sun, 16 Sep 2012 05:45:07 +0000 (22:45 -0700)
sub {
  my $x;
  sub { eval '$x' }
}->()()
__END__
Variable "$x" is not available at (eval 1) line 2.

That one’s OK (though I wonder about the line number).

sub {
  my sub x {};
  sub { eval '\&x' }
}->()()
__END__
Variable "&x" is not available at (eval 1) line 1.

That should say ‘Subroutine’.

pad.c
pod/perldiag.pod
t/cmd/lexsub.t
t/porting/diag.t

diff --git a/pad.c b/pad.c
index 454d842..195e737 100644 (file)
--- a/pad.c
+++ b/pad.c
@@ -1238,8 +1238,12 @@ S_pad_findlex(pTHX_ const char *namepv, STRLEN namelen, U32 flags, const CV* cv,
                        : *out_flags & PAD_FAKELEX_ANON)
                {
                    if (warn)
+                       /* diag_listed_as: Variable "%s" is not available*/
                        Perl_ck_warner(aTHX_ packWARN(WARN_CLOSURE),
-                                      "Variable \"%"SVf"\" is not available",
+                                      "%se \"%"SVf"\" is not available",
+                                      *namepv == '&'
+                                        ? "Subroutin"
+                                        : "Variabl",
                                        newSVpvn_flags(namepv, namelen,
                                            SVs_TEMP |
                                            (flags & padadd_UTF8_NAME ? SVf_UTF8 : 0)));
@@ -1287,8 +1291,12 @@ S_pad_findlex(pTHX_ const char *namepv, STRLEN namelen, U32 flags, const CV* cv,
                        && (!CvDEPTH(cv) || !staleok)
                        && !SvPAD_STATE(name_svp[offset]))
                    {
+                       /* diag_listed_as: Variable "%s" is not available*/
                        Perl_ck_warner(aTHX_ packWARN(WARN_CLOSURE),
-                                      "Variable \"%"SVf"\" is not available",
+                                      "%se \"%"SVf"\" is not available",
+                                      *namepv == '&'
+                                        ? "Subroutin"
+                                        : "Variabl",
                                        newSVpvn_flags(namepv, namelen,
                                            SVs_TEMP |
                                            (flags & padadd_UTF8_NAME ? SVf_UTF8 : 0)));
index 82aa423..47e0adb 100644 (file)
@@ -4561,6 +4561,36 @@ was either never opened or has since been closed.
 stubs.  Stubs should never be implicitly created, but explicit calls to
 C<can> may break this.
 
+=item Subroutine "&%s" is not available
+
+(W closure) During compilation, an inner named subroutine or eval is
+attempting to capture an outer lexical subroutine that is not currently
+available.  This can happen for one of two reasons.  First, the lexical
+subroutine may be declared in an outer anonymous subroutine that has not
+yet been created.  (Remember that named subs are created at compile time,
+while anonymous subs are created at run-time.)  For example,
+
+    sub { my sub a {...} sub f { \&a } }
+
+At the time that f is created, it can't capture the current the "a" sub,
+since the anonymous subroutine hasn't been created yet.  Conversely, the
+following won't give a warning since the anonymous subroutine has by now
+been created and is live:
+
+    sub { my sub a {...} eval 'sub f { \&a }' }->();
+
+The second situation is caused by an eval accessing a variable that has
+gone out of scope, for example,
+
+    sub f {
+       my sub a {...}
+       sub { eval '\&a' }
+    }
+    f()->();
+
+Here, when the '\&a' in the eval is being compiled, f() is not currently
+being executed, so its &a is not available for capture.
+
 =item "%s" subroutine &%s masks earlier declaration in same %s
 
 (W misc) A "my" or "state" subroutine has been redeclared in the
index 02ebac7..c3934ba 100644 (file)
@@ -8,7 +8,7 @@ BEGIN {
     *bar::like = *like;
 }
 no warnings 'deprecated';
-plan 113;
+plan 115;
 
 # -------------------- our -------------------- #
 
@@ -489,6 +489,28 @@ sub make_anon_with_my_sub{
   eval "#line 56 pygpyf\nsub redef {}";
   is $w, "Subroutine redef redefined at pygpyf line 56.\n",
          "sub redefinition warnings from my subs";
+
+  undef $w;
+  sub {
+    my sub x {};
+    sub { eval "#line 87 khaki\n\\&x" }
+  }->()();
+  is $w, "Subroutine \"&x\" is not available at khaki line 87.\n",
+         "unavailability warning during compilation of eval in closure";
+
+  undef $w;
+  no warnings 'void';
+  eval <<'->()();';
+#line 87 khaki
+    sub {
+      my sub x{}
+      sub not_lexical8 {
+        \&x
+      }
+    }
+->()();
+  is $w, "Subroutine \"&x\" is not available at khaki line 90.\n",
+         "unavailability warning during compilation of named sub in anon";
 }
 
 # -------------------- Interactions (and misc tests) -------------------- #
index 31a1e29..4dcdf3b 100644 (file)
@@ -230,7 +230,7 @@ sub check_file {
       $sub = $_;
     }
     next if $sub =~ m/^XS/;
-    if (m</\* diag_listed_as: (.*) \*/>) {
+    if (m</\*\s*diag_listed_as: (.*?)\s*\*/>) {
       $listed_as = $1;
       $listed_as_line = $.+1;
     }