This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Make lv keys distinguish scalar/list cx properly
authorFather Chrysostomos <sprout@cpan.org>
Fri, 10 Jun 2016 15:49:59 +0000 (08:49 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Sat, 11 Jun 2016 13:17:01 +0000 (06:17 -0700)
commite4fc70828d25802f8f511e75d50813489648c124
tree0a65d172f4d52ef2f613832db1277a842e1ae8c8
parent7720b61be266a671fcf072b6d38f8a2b3bc34eda
Make lv keys distinguish scalar/list cx properly

keys(%h) was special in that it did not use the same code path as
other ops that distinguish between scalar and list lvalue context.
Consequently, some scalar lvalue contexts worked:

    keys %h = 3;
    ${\scalar keys %h} = 3;
    sub { $_[0] = 3 }->(scalar keys %h);
    foreach(scalar keys %h) { $_ = 3 }
    grep { $_ = 3 } scalar keys %h;
    substr keys %h, 0, = 3;

while others did not:

    keys %h .= 0;
    read FH, keys %h, 0;

Fixing other bugs in the same code paths without breaking keys (or
adding *more* exceptions) is harder to do if keys is not consistent.
So this commit allows .= and read to assign to keys, by using the same
internal code (scalar_mod_type) that determines whether %h assignment
is allowed.  The logic is reversed (since %h is list-only and keys %h
is scalar-only), so where %h is a valid lvalue keys %h is not, and
vice versa.
op.c
t/comp/parser.t