Skip to content

Commit 6dbe945

Browse files
committed
For now, forbid all list assignment initialisation of state variables,
as the precise semantics in Perl 6 are not clear. Better to make it a syntax error, than to have one behaviour now, but change it later. [I believe that this is the consensus. If not, it will be backed out] p4raw-id: //depot/perl@31824
1 parent aab6a79 commit 6dbe945

File tree

3 files changed

+83
-12
lines changed

3 files changed

+83
-12
lines changed

op.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3968,6 +3968,8 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
39683968
}
39693969

39703970
if (is_list_assignment(left)) {
3971+
static const char no_list_state[] = "Initialization of state variables"
3972+
" in list context currently forbidden";
39713973
OP *curop;
39723974

39733975
PL_modcount = 0;
@@ -4061,6 +4063,54 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
40614063
o->op_private |= OPpASSIGN_COMMON;
40624064
}
40634065

4066+
if ((left->op_type == OP_LIST
4067+
|| (left->op_type == OP_NULL && left->op_targ == OP_LIST))) {
4068+
OP* lop = ((LISTOP*)left)->op_first;
4069+
while (lop) {
4070+
if (lop->op_type == OP_PADSV ||
4071+
lop->op_type == OP_PADAV ||
4072+
lop->op_type == OP_PADHV ||
4073+
lop->op_type == OP_PADANY) {
4074+
if (lop->op_private & OPpPAD_STATE) {
4075+
if (left->op_private & OPpLVAL_INTRO) {
4076+
/* Each variable in state($a, $b, $c) = ... */
4077+
}
4078+
else {
4079+
/* Each state variable in
4080+
(state $a, my $b, our $c, $d, undef) = ... */
4081+
}
4082+
yyerror(no_list_state);
4083+
} else {
4084+
/* Each my variable in
4085+
(state $a, my $b, our $c, $d, undef) = ... */
4086+
}
4087+
} else {
4088+
/* Other ops in the list. undef may be interesting in
4089+
(state $a, undef, state $c) */
4090+
}
4091+
lop = lop->op_sibling;
4092+
}
4093+
}
4094+
else if (((left->op_private & (OPpLVAL_INTRO | OPpPAD_STATE))
4095+
== (OPpLVAL_INTRO | OPpPAD_STATE))
4096+
&& ( left->op_type == OP_PADSV
4097+
|| left->op_type == OP_PADAV
4098+
|| left->op_type == OP_PADHV
4099+
|| left->op_type == OP_PADANY))
4100+
{
4101+
/* All single variable list context state assignments, hence
4102+
state ($a) = ...
4103+
(state $a) = ...
4104+
state @a = ...
4105+
state (@a) = ...
4106+
(state @a) = ...
4107+
state %a = ...
4108+
state (%a) = ...
4109+
(state %a) = ...
4110+
*/
4111+
yyerror(no_list_state);
4112+
}
4113+
40644114
if (right && right->op_type == OP_SPLIT && !PL_madskills) {
40654115
OP* tmpop = ((LISTOP*)right)->op_first;
40664116
if (tmpop && (tmpop->op_type == OP_PUSHRE)) {

pod/perldiag.pod

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1999,6 +1999,13 @@ either consume text or fail.
19991999
The <-- HERE shows in the regular expression about where the problem was
20002000
discovered.
20012001

2002+
=item Initialization of state variables in list context currently forbidden
2003+
2004+
(F) Currently the implementation of "state" only permits the initialization
2005+
of scalar variables in scalar context. Re-write C<state ($a) = 42> as
2006+
C<state $a = 42> to change from list to scalar context. Constructions such
2007+
as C<state (@a) = foo()> will be supported in a future perl release.
2008+
20022009
=item Insecure dependency in %s
20032010

20042011
(F) You tried to do something that the tainting mechanism didn't like.

t/op/state.t

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ BEGIN {
1010
use strict;
1111
use feature ":5.10";
1212

13-
plan tests => 108;
13+
plan tests => 117;
1414

1515
ok( ! defined state $uninit, q(state vars are undef by default) );
1616

@@ -300,17 +300,6 @@ foreach my $x (0 .. 4) {
300300
}
301301

302302

303-
#
304-
# List context reassigns, but scalar doesn't.
305-
#
306-
my @swords = qw [Stormbringer Szczerbiec Grimtooth Corrougue];
307-
foreach my $sword (@swords) {
308-
state ($s1) = state $s2 = $sword;
309-
is $s1, $swords [0], 'mixed context';
310-
is $s2, $swords [0], 'mixed context';
311-
}
312-
313-
314303
#
315304
# Use with given.
316305
#
@@ -331,3 +320,28 @@ foreach my $spam (@spam) {
331320
state $x = "two";
332321
is $x, "two", "masked"
333322
}
323+
324+
foreach my $forbidden (<DATA>) {
325+
chomp $forbidden;
326+
no strict 'vars';
327+
eval $forbidden;
328+
like $@, qr/Initialization of state variables in list context currently forbidden/, "Currently forbidden: $forbidden";
329+
}
330+
__DATA__
331+
state ($a) = 1;
332+
(state $a) = 1;
333+
state @a = 1;
334+
state (@a) = 1;
335+
(state @a) = 1;
336+
state %a = ();
337+
state (%a) = ();
338+
(state %a) = ();
339+
state ($a, $b) = ();
340+
state ($a, @b) = ();
341+
(state $a, state $b) = ();
342+
(state $a, $b) = ();
343+
(state $a, my $b) = ();
344+
(state $a, state @b) = ();
345+
(state $a, local @b) = ();
346+
(state $a, undef, state $b) = ();
347+
state ($a, undef, $b) = ();

0 commit comments

Comments
 (0)