Skip to content

Commit 260c8d6

Browse files
committed
Warn when refalias desynchronises a closure-captured variable
The `refalias` feature is currently experimental due to a number of limitations of its implementation, most notably the effect it has on closures such as the one illustrated in this unit test. Any change in implementation to make this case function as intended would be a large undertaking, so instead as a path towards being able to remove the experimental status from this feature, we consider this behaviour warning instead.
1 parent 969375f commit 260c8d6

File tree

3 files changed

+23
-1
lines changed

3 files changed

+23
-1
lines changed

pod/perldiag.pod

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8328,6 +8328,15 @@ anonymous, using the C<sub {}> syntax. When inner anonymous subs that
83288328
reference variables in outer subroutines are created, they
83298329
are automatically rebound to the current values of such variables.
83308330

8331+
=item Variable "%s" will not stay shared after refalias
8332+
8333+
(W closure) A refalias operation has been performed on a variable that is
8334+
captured by one or more closures, and thus is shared between them. As a
8335+
result of the way it is currently implemented, the variable in the scope
8336+
that performed has now become disconnected from those in other scopes, and
8337+
now operates independently. Updates to this variable will not be reflected
8338+
in the others, or vice versa.
8339+
83318340
=item vector argument not supported with alpha versions
83328341

83338342
(S printf) The %vd (s)printf format does not support version objects

pp.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7624,6 +7624,12 @@ PP(pp_refassign)
76247624
case 0:
76257625
{
76267626
SV * const old = PAD_SV(ARGTARG);
7627+
if(SvREFCNT(old) > 1) {
7628+
PADNAME *pn = PadlistNAMESARRAY(CvPADLIST(find_runcv(NULL)))[ARGTARG];
7629+
warner(packWARN(WARN_CLOSURE),
7630+
"Variable \"%" PNf "\" will not stay shared after refalias",
7631+
PNfARG(pn));
7632+
}
76277633
PAD_SETSV(ARGTARG, SvREFCNT_inc_NN(SvRV(sv)));
76287634
SvREFCNT_dec(old);
76297635
if ((PL_op->op_private & (OPpLVAL_INTRO|OPpPAD_STATE))

t/op/lvref.t

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ BEGIN {
55
set_up_inc("../lib");
66
}
77

8-
plan 203;
8+
plan 204;
99

1010
eval '\$x = \$y';
1111
like $@, qr/^Experimental aliasing via reference not enabled/,
@@ -626,6 +626,9 @@ like $@,
626626
# Miscellaneous
627627

628628
{
629+
my $warnings = "";
630+
local $SIG{__WARN__} = sub { $warnings .= $_[0]; };
631+
629632
local $::TODO = ' ';
630633
my($x,$y);
631634
sub {
@@ -635,6 +638,10 @@ like $@,
635638
is \$x, \$y, 'lexical alias affects outer closure';
636639
}->();
637640
is \$x, \$y, 'lexical alias affects outer sub where vars are declared';
641+
642+
undef $::TODO;
643+
like $warnings, qr/^Variable "\$x" will not stay shared after refalias /,
644+
'warning emitted by refalias on closure shared variable';
638645
}
639646

640647
{ # PADSTALE has a double meaning

0 commit comments

Comments
 (0)