summaryrefslogtreecommitdiff
path: root/pad.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2012-08-04 14:42:47 -0700
committerFather Chrysostomos <sprout@cpan.org>2012-08-04 15:56:22 -0700
commitcae5dbbe30ba4a96ff5e570be0d90779f06fee71 (patch)
tree5cf09fd30ac0981e861f9dda87ba20e486d67fbb /pad.c
parent3207fc6be298e308e8094e866ca339ba7e9a2790 (diff)
downloadperl-cae5dbbe30ba4a96ff5e570be0d90779f06fee71.tar.gz
Close over stale vars in active subs
\$x and sub { $x }->() should never produce different values. But this used to be possible because sub cloning (which happens with sub{...}) was written to avoid closing over variables that are not active. Not closing over inactive variables makes sense in cases like this (because the variable doesn’t really exist yet): sub { my $x; sub foo { $x } } foo; but the logic breaks down in cases like this (which was printing 3 only on the first print): sub foo { my $x; sub bar { $x = 3; print $x, "\n"; sub { print $x, "\n" }->() } } bar(); If bar can see a scalar named $x (even if it is questionable), sub { $x }->() should jolly well see the same scalar as the immedi- ately enclosing sub. The only case where a run-time cloning of a CV should refuse to close over the same scalar that the outer sub sees is when the outer sub is not running. That only happens with formats: sub f { my $x; format = @ $x . } write STDOUT; As of this commit, it does only happen with formats. The actual cases of subs refusing to close over stale variables in active parents have changed twice since 5.10.0. See the comments in the tests.
Diffstat (limited to 'pad.c')
-rw-r--r--pad.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/pad.c b/pad.c
index 71d5296b46..1e796e7ab4 100644
--- a/pad.c
+++ b/pad.c
@@ -2020,7 +2020,8 @@ Perl_cv_clone(pTHX_ CV *proto)
while my $x if $false can leave an active var marked as
stale. And state vars are always available */
if (!outpad || !(sv = outpad[PARENT_PAD_INDEX(namesv)])
- || (SvPADSTALE(sv) && !SvPAD_STATE(namesv))) {
+ || ( SvPADSTALE(sv) && !SvPAD_STATE(namesv)
+ && !CvDEPTH(outside)) ) {
Perl_ck_warner(aTHX_ packWARN(WARN_CLOSURE),
"Variable \"%"SVf"\" is not available", namesv);
sv = NULL;