summaryrefslogtreecommitdiff
path: root/t
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2012-07-26 12:38:14 -0700
committerFather Chrysostomos <sprout@cpan.org>2012-09-15 22:45:03 -0700
commit10342479afca0484c66269733fcc2f4a1fbabbb7 (patch)
treee3e43797240ed502e5f22246bb4d32ca997c7dbe /t
parent2a388207e072a645aa29f0b2b18f07d9a55cbf5e (diff)
downloadperl-10342479afca0484c66269733fcc2f4a1fbabbb7.tar.gz
Let state sub fwd decls and nested subs work in anons
I had this working: state sub foo; sub other { sub foo { # defines the state sub declared outside ... } } But it failed inside an anonymous subroutine: sub { state sub foo; sub other { sub foo { # defines the state sub declared outside ... } } } When an anonymous (or otherwise clonable) sub is cloned, any state vars, and, likewise, any state subs, inside it are cloned, too. In the first example above the state sub forward declaration creates a subroutine stub. The ‘other’ sub’s ‘sub foo’ declaration creates a pad entry in other’s pad that closes over the outer foo immediately, so the same stub is visible in two pads. The sub foo {} declaration uses that stub. When the outer sub containing the forward declaration is clonable, the pad entry is not closed over immediately at compile time, because the pad entry is just a prototype, not the actual value that will be shared by the clone and its nested subs. So the inner pad entry does not contain the sub. So the actual creation of the sub, if it only looks at the inner pad (other’s pad), will not see the stub, and will not attach a body to it. This was the result: $ ./miniperl -e 'CORE::state sub foo; CORE::state sub bar { sub foo {warn called} }; foo()' called at -e line 1. $ ./miniperl -e 'sub { CORE::state sub foo; CORE::state sub bar { sub foo {warn called} }; foo() }->()' Undefined subroutine &foo called at -e line 1. This commit fixes that by having newMYSUB follow the CvOUTSIDE chain to find the original pad entry where it defines the sub, if the for- ward declaration is occurs outside and has not been closed over yet.
Diffstat (limited to 't')
-rw-r--r--t/cmd/lexsub.t24
1 files changed, 23 insertions, 1 deletions
diff --git a/t/cmd/lexsub.t b/t/cmd/lexsub.t
index 157f5876c5..fa4ccdc5d2 100644
--- a/t/cmd/lexsub.t
+++ b/t/cmd/lexsub.t
@@ -8,7 +8,7 @@ BEGIN {
*bar::like = *like;
}
no warnings 'deprecated';
-plan 104;
+plan 106;
# -------------------- our -------------------- #
@@ -155,6 +155,17 @@ is do foo(), 43, 'state sub falling out of scope (called via amper)';
}
is eval{sb3}, 47,
'sub foo{} applying to "state sub foo;" even inside state sub foo{}';
+ # Same test again, but inside an anonymous sub
+ sub {
+ state sub sb4;
+ {
+ state sub sb4 {
+ sub sb4 { 47 }
+ }
+ }
+ is sb4, 47,
+ 'sub foo{} applying to "state sub foo;" even inside state sub foo{}';
+ }->();
}
sub sc { 43 }
{
@@ -342,6 +353,17 @@ is do foo(), 43, 'my sub falling out of scope (called via amper)';
}
is eval{mb3}, 47,
'sub foo{} applying to "my sub foo;" even inside my sub foo{}';
+ # Same test again, but inside an anonymous sub
+ sub {
+ my sub mb4;
+ {
+ my sub mb4 {
+ sub mb4 { 47 }
+ }
+ }
+ is mb4, 47,
+ 'sub foo{} applying to "my sub foo;" even inside my sub foo{}';
+ }->();
}
sub mc { 43 }
{