diff options
author | David Mitchell <davem@iabyn.com> | 2020-08-11 11:55:46 +0100 |
---|---|---|
committer | Steve Hay <steve.m.hay@googlemail.com> | 2021-01-06 17:38:54 +0000 |
commit | 1da7e62b5d41e8aff3a324906226a6b22ba7fce9 (patch) | |
tree | e28eb1da7c817c5ed8d3e512750ad58b4fbb876e | |
parent | 65b6c72dc5b11fc6720882edd4fb14f919e83af9 (diff) | |
download | perl-1da7e62b5d41e8aff3a324906226a6b22ba7fce9.tar.gz |
list assign in list context was over-optimising
GH #17816
This code:
my $x = 1;
print (($x, undef) = (2 => $x));
was printing "22" when it should have been printing "21".
An optimisation skips the 'common values on both sides' test
when the LHS of an assign only contains a single var; as the example
above shows, this is not sufficient.
This was broken by v5.23.1-202-g808ce55782
This commit fixes it by counting undef's on the LHS towards the var
count if they don't appear first.
(cherry picked from commit 5b354d2a8a6fea46c62048464c6722560cb1c907)
-rw-r--r-- | op.c | 10 | ||||
-rw-r--r-- | t/op/aassign.t | 10 |
2 files changed, 17 insertions, 3 deletions
@@ -15724,11 +15724,15 @@ S_aassign_scan(pTHX_ OP* o, bool rhs, int *scalars_p) goto do_next; case OP_UNDEF: - /* undef counts as a scalar on the RHS: - * (undef, $x) = ...; # only 1 scalar on LHS: always safe + /* undef on LHS following a var is significant, e.g. + * my $x = 1; + * @a = (($x, undef) = (2 => $x)); + * # @a shoul be (2,1) not (2,2) + * + * undef on RHS counts as a scalar: * ($x, $y) = (undef, $x); # 2 scalars on RHS: unsafe */ - if (rhs) + if ((!rhs && *scalars_p) || rhs) (*scalars_p)++; flags = AAS_SAFE_SCALAR; break; diff --git a/t/op/aassign.t b/t/op/aassign.t index ed904adc62..9128f9fd98 100644 --- a/t/op/aassign.t +++ b/t/op/aassign.t @@ -594,4 +594,14 @@ SKIP: { is ($fill, 2, "RT #130132 array 2"); } +{ + # GH #17816 + # don't use the "1-arg on LHS can't be common" optimisation + # when there are undef's there + my $x = 1; + my @a = (($x, undef) = (2 => $x)); + is("@a", "2 1", "GH #17816"); +} + + done_testing(); |