There's no way to guess at compile time if the scalar will be modified, such as in "eval '$_ = 1' for $x->{key}". Practically, there's no way to distinguish the xelem op from the one you get for "$x->{key} = $val". I was going against the interpreter's will and this is my defeat.
This commit partially reverts
ddbfd527f4c54458985145aae3a837a8f5868551.
if (PL_op == oi.root) { /* This means "%$hashref" */
PL_op->op_ppaddr = oi.old_pp;
} else if (!SvOK(TOPs)) {
if (PL_op == oi.root) { /* This means "%$hashref" */
PL_op->op_ppaddr = oi.old_pp;
} else if (!SvOK(TOPs)) {
- if (oi.root->op_flags & OPf_MOD) {
- SV *hv;
- POPs;
- hv = sv_2mortal((SV *) newHV());
- PUSHs(hv);
- }
} else if (flags && (PL_op->op_private & OPpDEREF || PL_op == oi.root)) {
oi.flags = flags & A_HINT_NOTIFY;
} else if (flags && (PL_op->op_private & OPpDEREF || PL_op == oi.root)) {
oi.flags = flags & A_HINT_NOTIFY;
- if ((oi.root->op_flags & (OPf_MOD|OPf_REF)) != (OPf_MOD|OPf_REF)) {
- if (flags & A_HINT_FETCH)
- oi.flags |= (A_HINT_FETCH|A_HINT_DEREF);
- } else if (flags & A_HINT_STORE)
+ if (oi.root->op_flags & OPf_MOD) {
+ if (flags & A_HINT_STORE)
oi.flags |= (A_HINT_STORE|A_HINT_DEREF);
oi.flags |= (A_HINT_STORE|A_HINT_DEREF);
+ } else if (flags & A_HINT_FETCH)
+ oi.flags |= (A_HINT_FETCH|A_HINT_DEREF);
if (PL_op == oi.root)
oi.flags &= ~A_HINT_DEREF;
if (PL_op == oi.root)
oi.flags &= ~A_HINT_DEREF;
-Turn off autovivification for lvalue dereferencing expressions, such as C<< $hashref->{key}[$idx]{$field} = $value >>.
+Turn off autovivification for lvalue dereferencing expressions, such as C<< $hashref->{key}[$idx]{$field} = $value >> or C<< for ($hashref->{key}[$idx]{$field}) { ... } >>.
An exception is thrown if vivification is needed to store the value, which means that effectively you can only assign to levels that are already defined (in the example, this would require C<< $hashref->{key}[$idx] >> to already be a hash reference).
=item *
An exception is thrown if vivification is needed to store the value, which means that effectively you can only assign to levels that are already defined (in the example, this would require C<< $hashref->{key}[$idx] >> to already be a hash reference).
=item *
--- aliasing ---
$x # 1 for $x->{a}; () # '', undef, { a => undef }
--- aliasing ---
$x # 1 for $x->{a}; () # '', undef, { a => undef }
-$x # 1 for $x->{a}; () # '', undef, undef #
-$x # 1 for $x->{a}; () # '', undef, undef # +fetch
+$x # 1 for $x->{a}; () # '', undef, { a => undef } #
+$x # 1 for $x->{a}; () # '', undef, { a => undef } # +fetch
$x # 1 for $x->{a}; () # '', undef, { a => undef } # +exists
$x # 1 for $x->{a}; () # '', undef, { a => undef } # +delete
$x # 1 for $x->{a}; () # '', undef, { a => undef } # +exists
$x # 1 for $x->{a}; () # '', undef, { a => undef } # +delete
-$x # 1 for $x->{a}; () # '', undef, { a => undef } # +store
+$x # 1 for $x->{a}; () # qr/^Can't vivify reference/, undef, undef # +store
$x # $_ = 1 for $x->{a}; () # '', undef, { a => 1 }
$x # $_ = 1 for $x->{a}; () # '', undef, { a => 1 }
-$x # $_ = 1 for $x->{a}; () # '', undef, undef #
-$x # $_ = 1 for $x->{a}; () # '', undef, undef # +fetch
+$x # $_ = 1 for $x->{a}; () # '', undef, { a => 1 } #
+$x # $_ = 1 for $x->{a}; () # '', undef, { a => 1 } # +fetch
$x # $_ = 1 for $x->{a}; () # '', undef, { a => 1 } # +exists
$x # $_ = 1 for $x->{a}; () # '', undef, { a => 1 } # +delete
$x # $_ = 1 for $x->{a}; () # '', undef, { a => 1 } # +exists
$x # $_ = 1 for $x->{a}; () # '', undef, { a => 1 } # +delete
-$x # $_ = 1 for $x->{a}; () # '', undef, { a => 1 } # +store
+$x # $_ = 1 for $x->{a}; () # qr/^Can't vivify reference/, undef, undef # +store
$x->{a} = 1 # 1 for $x->{a}; () # '', undef, { a => 1 } # +fetch
$x->{a} = 1 # 1 for $x->{b}; () # '', undef, { a => 1, b => undef } # +fetch
$x->{a} = 1 # 1 for $x->{a}; () # '', undef, { a => 1 } # +fetch
$x->{a} = 1 # 1 for $x->{b}; () # '', undef, { a => 1, b => undef } # +fetch
--- aliasing ---
$x # 1 for $x->[0]; () # '', undef, [ undef ]
--- aliasing ---
$x # 1 for $x->[0]; () # '', undef, [ undef ]
-$x # 1 for $x->[0]; () # '', undef, undef #
-$x # 1 for $x->[0]; () # '', undef, undef # +fetch
+$x # 1 for $x->[0]; () # '', undef, [ undef ] #
+$x # 1 for $x->[0]; () # '', undef, [ undef ] # +fetch
$x # 1 for $x->[0]; () # '', undef, [ undef ] # +exists
$x # 1 for $x->[0]; () # '', undef, [ undef ] # +delete
$x # 1 for $x->[0]; () # '', undef, [ undef ] # +exists
$x # 1 for $x->[0]; () # '', undef, [ undef ] # +delete
-$x # 1 for $x->[0]; () # '', undef, [ undef ] # +store
+$x # 1 for $x->[0]; () # qr/^Can't vivify reference/, undef, undef # +store
$x # $_ = 1 for $x->[0]; () # '', undef, [ 1 ]
$x # $_ = 1 for $x->[0]; () # '', undef, [ 1 ]
-$x # $_ = 1 for $x->[0]; () # '', undef, undef #
-$x # $_ = 1 for $x->[0]; () # '', undef, undef # +fetch
+$x # $_ = 1 for $x->[0]; () # '', undef, [ 1 ] #
+$x # $_ = 1 for $x->[0]; () # '', undef, [ 1 ] # +fetch
$x # $_ = 1 for $x->[0]; () # '', undef, [ 1 ] # +exists
$x # $_ = 1 for $x->[0]; () # '', undef, [ 1 ] # +delete
$x # $_ = 1 for $x->[0]; () # '', undef, [ 1 ] # +exists
$x # $_ = 1 for $x->[0]; () # '', undef, [ 1 ] # +delete
-$x # $_ = 1 for $x->[0]; () # '', undef, [ 1 ] # +store
+$x # $_ = 1 for $x->[0]; () # qr/^Can't vivify reference/, undef, undef # +store
$x->[0] = 1 # 1 for $x->[0]; () # '', undef, [ 1 ] # +fetch
$x->[0] = 1 # 1 for $x->[1]; () # '', undef, [ 1, undef ] # +fetch
$x->[0] = 1 # 1 for $x->[0]; () # '', undef, [ 1 ] # +fetch
$x->[0] = 1 # 1 for $x->[1]; () # '', undef, [ 1, undef ] # +fetch