Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Experimental refaliasing with local not restoring values when scope exited #14765

Closed
p5pRT opened this issue Jun 19, 2015 · 5 comments
Closed

Comments

@p5pRT
Copy link

p5pRT commented Jun 19, 2015

Migrated from rt.perl.org#125436 (status was 'rejected')

Searchable as RT125436$

@p5pRT
Copy link
Author

p5pRT commented Jun 19, 2015

From kencotterill@netspace.net.au

 

 
 
 
  [Note​: I used the 'perlbug' utility about 10
  hours ago. As I haven't received an automated reply, I'm following
  the advice from that utility and resending manually. I've kept the
  "Subject​:" lines the same.]

 

  In the original, I chose​:

 

  Category​: core

  Severity​: medium

 

  This bug relates to the experimental feature 'refaliasing'
  described in​:
http​://search.cpan.org/~rjbs/perl-5.22.0/pod/perlref.pod#Assigning_to_References

 

  My expectation was that using the " \local our " form would restore values when the scope of the ' local ' was exited.

 

  This wasn't the case and the observed behaviour was identical to
  using the " \our " form.

 

 

  Test code​:

  -------------------------------

 
  #!/usr/bin/env perl

use 5.022;
use warnings;
use feature 'refaliasing';
no warnings 'experimental​::refaliasing';

@​​::data = (1 .. 3);

say "Data before pop_sum​: @​​::data";
say "Sum of data​: ", pop_sum(\@​​::data);
say "Data after pop_sum​: @​​::data";
say '---';
say "Data before pop_sum_ref​: @​​::data";
say "Sum of data​: ", pop_sum_ref(\@​​::data);
say "Data after pop_sum_ref​: @​​::data";

sub pop_sum {
  local our @​data = @​{+shift};

  my $total = 0;

  say "\tTotal​: $total; Data​: @​data";

  while (1) {
  $total += pop @​data;
  say "\tTotal​: $total; Data​: @​data";
  last if $#data < 0;
  }

  return $total;
}

sub pop_sum_ref {
  \local our @​data = shift;

  my $total = 0;

  say "\tTotal​: $total; Data​: @​data";

  while (1) {
  $total += pop @​data;
  say "\tTotal​: $total; Data​: @​data";
  last if $#data < 0;
  }

  return $total;
}

  -------------------------------

 

 

  Output​:

  -------------------------------

 
  Data before pop_sum​: 1 2 3
  Total​: 0; Data​: 1 2 3
  Total​: 3; Data​: 1 2
  Total​: 5; Data​: 1
  Total​: 6; Data​:
Sum of data​: 6
Data after pop_sum​: 1 2 3


Data before pop_sum_ref​: 1 2 3
  Total​: 0; Data​: 1 2 3
  Total​: 3; Data​: 1 2
  Total​: 5; Data​: 1
  Total​: 6; Data​:
Sum of data​: 6
Data after pop_sum_ref​:

  -------------------------------

 

 

  My (unrealised) expectation for the
  last line of output was​:

  -------------------------------

 
  Data after pop_sum_ref​: 1 2 3

  -------------------------------

 

 

  Changing

  ------------------------------

  sub
  pop_sum_ref {

      \local our @​data = shift;

  -------------------------------

  to

  -------------------------------

  sub
  pop_sum_ref {

      \our @​data = shift;

  -------------------------------

  made
  no difference
  to the output.

 

 

  perl
  -V output​:

  -------------------------------

 
  Summary of my perl5 (revision 5 version 22 subversion 0) configuration​:
 
  Platform​:
  osname=darwin, osvers=14.3.0, archname=darwin-thread-multi-2level
  uname='darwin ganymede.local 14.3.0 darwin kernel version 14.3.0​: mon mar 23 11​:59​:05 pdt 2015; root​:xnu-2782.20.48~5release_x86_64 x86_64 '
  config_args='-de -Dprefix=/Users/ken/perl5/perlbrew/perls/perl-5.22.0t -Dusethreads -Aeval​:scriptdir=/Users/ken/perl5/perlbrew/perls/perl-5.22.0t/bin'
  hint=recommended, useposix=true, d_sigaction=define
  useithreads=define, usemultiplicity=define
  use64bitint=define, use64bitall=define, uselongdouble=undef
  usemymalloc=n, bincompat5005=undef
  Compiler​:
  cc='cc', ccflags ='-fno-common -DPERL_DARWIN -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -I/opt/local/include',
  optimize='-O3',
  cppflags='-fno-common -DPERL_DARWIN -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -I/opt/local/include'
  ccversion='', gccversion='4.2.1 Compatible Apple LLVM 6.1.0 (clang-602.0.49)', gccosandvers=''
  intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678, doublekind=3
  d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16, longdblkind=3
  ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
  alignbytes=8, prototype=define
  Linker and Libraries​:
  ld='env MACOSX_DEPLOYMENT_TARGET=10.3 cc', ldflags =' -fstack-protector-strong -L/usr/local/lib -L/opt/local/lib'
  libpth=/usr/local/lib /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/6.1.0/lib /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib /usr/lib /opt/local/lib
  libs=-lpthread -lgdbm -ldbm -ldl -lm -lutil -lc
  perllibs=-lpthread -ldl -lm -lutil -lc
  libc=, so=dylib, useshrplib=false, libperl=libperl.a
  gnulibc_version=''
  Dynamic Linking​:
  dlsrc=dl_dlopen.xs, dlext=bundle, d_dlsymun=undef, ccdlflags=' '
  cccdlflags=' ', lddlflags=' -bundle -undefined dynamic_lookup -L/usr/local/lib -L/opt/local/lib -fstack-protector-strong'

Characteristics of this binary (from libperl)​:
  Compile-time options​: HAS_TIMES MULTIPLICITY PERLIO_LAYERS
  PERL_DONT_CREATE_GVSV
  PERL_HASH_FUNC_ONE_AT_A_TIME_HARD
  PERL_IMPLICIT_CONTEXT PERL_MALLOC_WRAP
  PERL_NEW_COPY_ON_WRITE PERL_PRESERVE_IVUV
  USE_64_BIT_ALL USE_64_BIT_INT USE_ITHREADS
  USE_LARGE_FILES USE_LOCALE USE_LOCALE_COLLATE
  USE_LOCALE_CTYPE USE_LOCALE_NUMERIC USE_LOCALE_TIME
  USE_PERLIO USE_PERL_ATOF USE_REENTRANT_API
  Locally applied patches​:
  Devel​::PatchPerl 1.32
  Built under darwin
  Compiled at Jun 4 2015 17​:53​:05
  %ENV​:
  PERL5LIB="/Users/ken/local/lib/perl"
  PERLBREW_BASHRC_VERSION="0.30"
  PERLBREW_HOME="/Users/ken/.perlbrew"
  PERLBREW_MANPATH="/Users/ken/perl5/perlbrew/perls/perl-5.22.0t/man"
  PERLBREW_PATH="/Users/ken/perl5/perlbrew/bin​:/Users/ken/perl5/perlbrew/perls/perl-5.22.0t/bin"
  PERLBREW_PERL="perl-5.22.0t"
  PERLBREW_ROOT="/Users/ken/perl5/perlbrew"
  PERLBREW_VERSION="0.73"
  @​INC​:
  /Users/ken/local/lib/perl
  /Users/ken/perl5/perlbrew/perls/perl-5.22.0t/lib/site_perl/5.22.0/darwin-thread-multi-2level
  /Users/ken/perl5/perlbrew/perls/perl-5.22.0t/lib/site_perl/5.22.0
  /Users/ken/perl5/perlbrew/perls/perl-5.22.0t/lib/5.22.0/darwin-thread-multi-2level
  /Users/ken/perl5/perlbrew/perls/perl-5.22.0t/lib/5.22.0
  .

  -------------------------------

 

  Not sure how useful
  this might be, but I discussed the issue on PerlMonks prior to
  raising the bug​: http​://www.perlmonks.org/?node_id=1130948

 

  Additional information available on request if required.

 

 

 
 

@p5pRT
Copy link
Author

p5pRT commented Jun 23, 2015

From @iabyn

On Thu, Jun 18, 2015 at 07​:12​:12PM -0700, Ken Cotterill wrote​:

This bug relates to the experimental feature 'refaliasing' described in​:
http​://search.cpan.org/~rjbs/perl-5.22.0/pod/perlref.pod#Assigning_to_References

My expectation was that using the "\local our" form would restore values when
the scope of the 'local' was exited.

This wasn't the case and the observed behaviour was identical to using the "\our"
form.

I don't think its a bug.

The first form is doing the equivalent of​:

  @​data = (1,2,3);
  {
  local @​data = @​data;
  @​data = ();
  }

which

  * creates a temporary new array;
  * updates the symbol table so that '@​data' temporarily refers to the
  new array; the original @​data array is still hanging around, hidden
  on the save stack, with its original (1,2,3) elements.
  * copies the elements of the original @​data to the new array;

and then
  * frees all the elements of the new temp array (i.e. the *copies* of
  (1,2,3);

and which on scope exit​:

  * frees the new temporary array and any elements it contains (which is
  none in this case as we earlier cleared the array);
  * updates the symbol table to make '@​data' refer again to the original
  array, which still contains the original (1,2,3).

The second form is doing the equivalent of​:

  @​data = (1,2,3);
  {
  \local @​data = \@​data;
  @​data = ();
  }

which

  * temporarily saves the old pointer to @​data in the symbol table
  on the save stack, then makes the entry point to the thing on the
  RHS, which in this case, is @​data​: i.e. the entry in the symbol
  table still points to the *same* array;

and then
  * frees all the elements of the @​data array (i.e. the original and only
  array)

and which on scope exit​:

  * restores the pointer in the symbol table to its original value
  (which since they're the same, is a no-op in this case);
  * so '@​data' still refers to the array which we've just emptied.

Note that if you did something like

  @​data = (1,2,3);
  {
  \local @​data = [4,5,6];
  @​data = ();
  }

then @​data *would* contain (1,2,3) at the end.

Or to put it another way,

  \local @​data = \XXX

localises the symbol table entry to whatever XXX is, while

  local @​data = XXX

localises the symbol table entry to a new array, and then populates the
new array with the elements of XXX.

(In the above, whenever I've referred to 'symbol table entry', technically
I've meant AV slot of the GV referenced from the 'data' entry in the
%main​:: symbol table).

--
I thought I was wrong once, but I was mistaken.

@p5pRT
Copy link
Author

p5pRT commented Jun 23, 2015

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Jun 23, 2015

From @ikegami

On Tue, Jun 23, 2015 at 7​:46 AM, Dave Mitchell <davem@​iabyn.com> wrote​:

On Thu, Jun 18, 2015 at 07​:12​:12PM -0700, Ken Cotterill wrote​:

This bug relates to the experimental feature 'refaliasing' described in​:

http​://search.cpan.org/~rjbs/perl-5.22.0/pod/perlref.pod#Assigning_to_References

My expectation was that using the "\local our" form would restore values
when
the scope of the 'local' was exited.

This wasn't the case and the observed behaviour was identical to using
the "\our"
form.

I don't think its a bug.

I agree.

`local our $x` is an attempt to approximate `my $x` using package variables.

If you change `local our @​data` for `my @​data` in the program, the
behaviour is the same, and you realize that it's the only behaviour that
makes sense.

#!/usr/bin/env perl

use 5.022;
use warnings;
use feature 'refaliasing';
no warnings 'experimental​::refaliasing';

my @​data = (1 .. 3);

say "Data before pop_sum​: @​data";
say "Sum of data​: ", pop_sum(\@​data);
say "Data after pop_sum​: @​data";
say '---';
say "Data before pop_sum_ref​: @​data";
say "Sum of data​: ", pop_sum_ref(\@​data);
say "Data after pop_sum_ref​: @​data";

sub pop_sum {
  my @​data = @​{+shift};

  my $total = 0;

  say "\tTotal​: $total; Data​: @​data";

  while (1) {
  $total += pop @​data;
  say "\tTotal​: $total; Data​: @​data";
  last if $#data < 0;
  }

  return $total;
}

sub pop_sum_ref {
  \my @​data = shift;

  my $total = 0;

  say "\tTotal​: $total; Data​: @​data";

  while (1) {
  $total += pop @​data;
  say "\tTotal​: $total; Data​: @​data";
  last if $#data < 0;
  }

  return $total;
}

@p5pRT p5pRT closed this as completed Jun 24, 2015
@p5pRT
Copy link
Author

p5pRT commented Jun 24, 2015

@iabyn - Status changed from 'open' to 'rejected'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant