This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #35865, #43011] FETCH after autovivifying
authorFather Chrysostomos <sprout@cpan.org>
Tue, 10 Jan 2012 16:55:08 +0000 (08:55 -0800)
committerFather Chrysostomos <sprout@cpan.org>
Tue, 10 Jan 2012 16:55:26 +0000 (08:55 -0800)
commit7e482323fb2aaa4e52b80f3c50b716c8b6ef41c8
tree731b8d9c5678c5118861ed33a42c4a699cd0985c
parent47d235f1839af4a64487fd5c07a58ff1b937da7c
[perl #35865, #43011] FETCH after autovivifying

After autovivification, perl should not assume that the value it has
assigned to a magical scalar is the one that would have been returned.

The result of this assumption is that any tie class that copies things
assigned to it will cause autovivification to assign to a temporary
aggregate without warning, in cases like this:

    $tied{nonexistent}{foo} = 7;

The hash implicitly assigned to $tied{nonexistent} ends up being freed
after the =7 assignment.

This commit changes autovivification to do FETCH immediately after
doing STORE.

This required changing some recently-added tests in gmagic.t.

Without this change, you end up with horrific workarounds (using B.pm
to get the reference count), like the one in JE::Object (which I’m
pasting here, in case it has changed by the time you read this):

sub STORE    {
my($self, $key, $val) = @_;
my $global = $self->global;
if(ref $val eq 'HASH' && !blessed $val
      && !%$val && svref_2object($val)->REFCNT == 2) {
$val = tie %$val, __PACKAGE__, __PACKAGE__->new(
$global);
} elsif (ref $val eq 'ARRAY' && !blessed $val && !@$val &&
         svref_2object($val)->REFCNT == 2) {
require JE::Object::Array;
$val = tie @$val, 'JE::Object::Array',
JE::Object::Array->new($global);
}
$self->prop($key => $global->upgrade($val))
}
pp_hot.c
t/op/gmagic.t
t/op/tie.t