This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Stop flip from returning the same scalar each time
authorFather Chrysostomos <sprout@cpan.org>
Tue, 23 Sep 2014 04:48:48 +0000 (21:48 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Tue, 23 Sep 2014 04:56:36 +0000 (21:56 -0700)
commit14d91147b4bfd5289f2548af3eb0d745d241b9f8
treec0a9c91dc617c129c50f17e9d8e3819c27cb73e3
parent39ff6c37b02dc106ce36a529c4fdd80ac93c7ada
Stop flip from returning the same scalar each time

sub f {
  for my $n (1..5) {
    my $x = \scalar($n == 2 .. $n == 4);
    $_ = $x if $n == 1;
    print "$n: $$_\n";
  }
  print("-----\n"), f() if @_
}
f(1);

Output:

1:
2: 1
3: 2
4: 3E0
5:
-----
1:
2:
3:
4:
5:

When f() is called, it evaluates a flipflop five times.  It takes a
reference to the return value the first time, and prints that same
scalar for each iteration.

Notice how the very same scalar is returned each time in the outer sub
call, but the recursive call hides that implementation detail.

.. should not be returning the same scalar each time, or at least that
implementation detail should not leak through.  (Most operators do
reuse the same scalar, but the scalar is flagged such that \ will copy
it, hiding that fact.)

This was happening because of the eccentric way that the flipflop
targets are allocated in the pad.  They are allocated as PADMY (i.e.,
like ‘my’ variables), but without a name.  pad_push (which creates a
new pad for recursion) assumes that anything without a name is PADTMP
instead (copy on reference).  So the recursive call behaves correctly.

I am not sure why the targets were allocated with PADMY to begin with.
(This goes back to perl 5.000.)  But now the PADMY prevents the tar-
gets from being shared with other ops under USE_PAD_RESET builds.

The better way to allocate these targets is to use PADMY as before,
but actually give those slots names.  The target that gets returned
needs to be marked PADTMP, so we also need to copy that flag
in pad_push.
op.c
pad.c
t/op/flip.t