Skip to content

Commit e4fc708

Browse files
author
Father Chrysostomos
committed
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.
1 parent 7720b61 commit e4fc708

File tree

2 files changed

+9
-2
lines changed

2 files changed

+9
-2
lines changed

op.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3042,7 +3042,7 @@ Perl_op_lvalue_flags(pTHX_ OP *o, I32 type, U32 flags)
30423042
break;
30433043

30443044
case OP_KEYS:
3045-
if (type != OP_SASSIGN && type != OP_LEAVESUBLV)
3045+
if (type != OP_LEAVESUBLV && !scalar_mod_type(NULL, type))
30463046
goto nomod;
30473047
goto lvalue_func;
30483048
case OP_SUBSTR:

t/comp/parser.t

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ BEGIN {
88
chdir 't' if -d 't';
99
}
1010

11-
print "1..182\n";
11+
print "1..185\n";
1212

1313
sub failed {
1414
my ($got, $expected, $name) = @_;
@@ -565,6 +565,13 @@ for my $marker (qw(
565565
like $@, qr/^Version control conflict marker at \(eval \d+\) line 3, near "$marker"/, "VCS marker '$marker' after operator";
566566
}
567567
568+
# keys assignments in weird contexts (mentioned in perl #128260)
569+
eval 'keys(%h) .= "00"';
570+
is $@, "", 'keys .=';
571+
eval 'sub { read $fh, keys %h, 0 }';
572+
is $@, "", 'read into keys';
573+
eval 'substr keys(%h),0,=3';
574+
is $@, "", 'substr keys assignment';
568575
569576
# Add new tests HERE (above this line)
570577

0 commit comments

Comments
 (0)