Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unexpected autovivification of arguments

Apparently my understanding of the no autovivification pragma is imperfect, as the not-dying-on-line-19 behaviour of the following script is extremely surprising to me.

use 5.014;
use strict;
use warnings;
no autovivification qw(fetch exists delete warn);

{
  my $foo = undef;
  my $thing = $foo->{bar};

  # this does not die, as expected
  die if defined $foo;
}

{
  my $foo = undef;
  do_nothing( $foo->{bar} );

  # I would expect this to die, but it doesn't
  die unless defined $foo;
}

sub do_nothing {
  return undef;
}

Running the script produces:

Reference was vivified at test.pl line 8.

The question: why is $foo autovivified when $foo->{bar} is supplied as an argument to a sub, even though no autovivification is in effect?

like image 722
ryanm Avatar asked Mar 08 '17 09:03

ryanm


1 Answers

In a subroutine call the arguments to a function are aliased in @_, so it must be possible to modify them. This provides an lvalue context, what will trigger autovivification.

When we look through descriptions of features you use in autovivification, they cover:

  • 'fetch' -- "rvalue dereferencing expressions"
  • 'exists' -- "dereferencing expressions that are parts of an exists"
  • 'delete' -- "dereferencing expressions that are parts of a delete"

None of these deal with lvalues (neither does warn).

To stop autovivification in subroutine calls as well you need to add store

Turns off autovivification for lvalue dereferencing expressions, such as :   [...]

where docs proceed with examples, including subroutine calls.

When I add it to your code,

no autovivification qw(fetch exists delete warn store);
# ...

I get

Reference was vivified at noautoviv.pl line 8.
Reference was vivified at noautoviv.pl line 16.
Died at noautoviv.pl line 19.
like image 81
zdim Avatar answered Oct 24 '22 03:10

zdim