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

local first sets to undef then assigns, but is documented to 'initialize' #14294

Open
p5pRT opened this issue Dec 2, 2014 · 22 comments
Open

Comments

@p5pRT
Copy link

p5pRT commented Dec 2, 2014

Migrated from rt.perl.org#123346 (status was 'open')

Searchable as RT123346$

@p5pRT
Copy link
Author

p5pRT commented Dec 2, 2014

From @epa

Created by @epa

The documentation of local() in perlsub says

  The argument list may be assigned to if desired, which allows
  you to initialize your local variables. (If no initializer is
  given for a particular variable, it is created with an
  undefined value.)

This led me to believe that

  local $x = 5;

would initialize $x with the value 5; that is, save the old value of
$x on a hidden stack and then assign 5 to it. That should differ from

  local $x;
  $x = 5;

which saves the value of $x, sets $x to undef, and then in the next
statement assigns 5 to it. But in practice it appears that the two do
the same thing​:

  #!/usr/bin/perl
  use strict;
  use warnings;
  use 5.018;
  our $VERSION = '0.0';
  package NewScalar;
  require Tie​::Scalar;
  our @​ISA = qw(Tie​::Scalar);
  sub FETCH { ${$_[0]} }
  sub TIESCALAR {
  my $t; return bless \$t, 'NewScalar';
  }
  sub STORE { say 'store ', $_[1] // 'undef'; ${$_[0]} = $_[1] }
  sub DESTROY { say 'destroy' }
  package main;
  our $x;
  tie $x, 'NewScalar' or die;
  $x = 1;
  { local $x = 2 }

Here I expected to see

  store 1 # first assignment
  store 2 # initialization with local
  store 1 # put back the old value on exiting block
  destroy

but instead the output is

  store 1
  store undef
  store 2
  store 1
  destroy

Why is the value undef being assigned to the variable before setting
it to 2? Surely C<local $x = 2> should set the value in one go,
without going through undef first.

Perl Info

Flags:
    category=core
    severity=low

Site configuration information for perl 5.18.4:

Configured by Red Hat, Inc. at Thu Oct 30 14:55:21 UTC 2014.

Summary of my perl5 (revision 5 version 18 subversion 4) configuration:
   
  Platform:
    osname=linux, osvers=3.16.3-200.fc20.x86_64, archname=x86_64-linux-thread-multi
    uname='linux buildvm-18.phx2.fedoraproject.org 3.16.3-200.fc20.x86_64 #1 smp wed sep 17 22:34:21 utc 2014 x86_64 x86_64 x86_64 gnulinux '
    config_args='-des -Doptimize=-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches  -m64 -mtune=generic -Dccdlflags=-Wl,--enable-new-dtags -Dlddlflags=-shared -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches  -m64 -mtune=generic -Wl,-z,relro  -Dshrpdir=/usr/lib64 -DDEBUGGING=-g -Dversion=5.18.4 -Dmyhostname=localhost -Dperladmin=root@localhost -Dcc=gcc -Dcf_by=Red Hat, Inc. -Dprefix=/usr -Dvendorprefix=/usr -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl5 -Dsitearch=/usr/local/lib64/perl5 -Dprivlib=/usr/share/perl5 -Dvendorlib=/usr/share/perl5/vendor_perl -Darchlib=/usr/lib64/perl5 -Dvendorarch=/usr/lib64/perl5/vendor_perl -Darchname=x86_64-linux-thread-multi -Dlibpth=/usr/local/lib64 /lib64 /usr/lib64 -Duseshrplib -Dusethreads -Duseithreads -Dusedtrace=/usr/bin/dtrace -Duselargefiles -Dd_semctl_semun -Di_db -Ui_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Duseperlio -Dinstallusrbinperl=n -Ubincompat5005 -Uversiononly -Dpager=/usr/bin/less -isr -Dd_gethostent_r_proto -Ud_endhostent_r_proto -Ud_sethostent_r_proto -Ud_endprotoent_r_proto -Ud_setprotoent_r_proto -Ud_endservent_r_proto -Ud_setservent_r_proto -Dscriptdir=/usr/bin -Dusesitecustomize'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=define, usemultiplicity=define
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='4.8.3 20140911 (Red Hat 4.8.3-7)', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='gcc', ldflags =' -fstack-protector'
    libpth=/usr/local/lib64 /lib64 /usr/lib64
    libs=-lresolv -lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lpthread -lc -lgdbm_compat
    perllibs=-lresolv -lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
    libc=, so=so, useshrplib=true, libperl=libperl.so
    gnulibc_version='2.18'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,--enable-new-dtags'
    cccdlflags='-fPIC', lddlflags='-shared -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -Wl,-z,relro '

Locally applied patches:
    Fedora Patch1: Removes date check, Fedora/RHEL specific
    Fedora Patch3: support for libdir64
    Fedora Patch4: use libresolv instead of libbind
    Fedora Patch5: USE_MM_LD_RUN_PATH
    Fedora Patch6: Skip hostname tests, due to builders not being network capable
    Fedora Patch7: Dont run one io test due to random builder failures
    Fedora Patch9: Fix find2perl to translate ? glob properly (RT#113054)
    Fedora Patch10: Update h2ph(1) documentation (RT#117647)
    Fedora Patch11: Update pod2html(1) documentation (RT#117623)
    Fedora Patch12: Disable ornaments on perl5db AutoTrace tests (RT#118817)
    Fedora Patch14: Do not use system Term::ReadLine::Gnu in tests (RT#118821)
    Fedora Patch15: Define SONAME for libperl.so
    Fedora Patch16: Install libperl.so to -Dshrpdir value
    Fedora Patch18: Fix crash with \\&$glob_copy (RT#119051)
    Fedora Patch19: Fix coreamp.t rand test (RT#118237)
    Fedora Patch20: Reap child in case where exception has been thrown (RT#114722)
    Fedora Patch21: Fix using regular expressions containing multiple code blocks (RT#117917)
    Fedora Patch22: Create site paths by cpan for the first time (CPAN RT#99905)
    Fedora Patch200: Link XS modules to libperl.so with EU::CBuilder on Linux
    Fedora Patch201: Link XS modules to libperl.so with EU::MM on Linux


@INC for perl 5.18.4:
    /home/eda/lib/perl5/
    /usr/local/lib64/perl5
    /usr/local/share/perl5
    /usr/lib64/perl5/vendor_perl
    /usr/share/perl5/vendor_perl
    /usr/lib64/perl5
    /usr/share/perl5
    .


Environment for perl 5.18.4:
    HOME=/home/eda
    LANG=en_GB.UTF-8
    LANGUAGE (unset)
    LC_COLLATE=C
    LC_CTYPE=en_GB.UTF-8
    LC_MESSAGES=en_GB.UTF-8
    LC_MONETARY=en_GB.UTF-8
    LC_NUMERIC=en_GB.UTF-8
    LC_TIME=en_GB.UTF-8
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/eda/bin:/home/eda/bin:/usr/local/bin:/usr/bin:/sbin:/usr/sbin:/sbin:/usr/sbin
    PERL5LIB=/home/eda/lib/perl5/
    PERL_BADLANG (unset)
    SHELL=/bin/bash

______________________________________________________________________
This email has been scanned by the Symantec Email Security.cloud service.
For more information please visit http://www.symanteccloud.com
______________________________________________________________________

@p5pRT
Copy link
Author

p5pRT commented Dec 2, 2014

From @cpansprout

On Tue Dec 02 06​:19​:28 2014, eda@​waniasset.com wrote​:

This is a bug report for perl from eda@​waniasset.com,
generated with the help of perlbug 1.39 running under perl 5.18.4.

-----------------------------------------------------------------
[Please describe your issue here]

The documentation of local() in perlsub says

The argument list may be assigned to if desired, which allows
you to initialize your local variables. (If no initializer is
given for a particular variable, it is created with an
undefined value.)

This led me to believe that

local $x = 5;

would initialize $x with the value 5; that is, save the old value of
$x on a hidden stack and then assign 5 to it. That should differ from

local $x;
$x = 5;

which saves the value of $x, sets $x to undef, and then in the next
statement assigns 5 to it. But in practice it appears that the two do
the same thing​:

#!/usr/bin/perl
use strict;
use warnings;
use 5.018;
our $VERSION = '0.0';
package NewScalar;
require Tie​::Scalar;
our @​ISA = qw(Tie​::Scalar);
sub FETCH { ${$_[0]} }
sub TIESCALAR {
my $t; return bless \$t, 'NewScalar';
}
sub STORE { say 'store ', $_[1] // 'undef'; ${$_[0]} = $_[1] }
sub DESTROY { say 'destroy' }
package main;
our $x;
tie $x, 'NewScalar' or die;
$x = 1;
{ local $x = 2 }

Here I expected to see

store 1 # first assignment
store 2 # initialization with local
store 1 # put back the old value on exiting block
destroy

but instead the output is

store 1
store undef
store 2
store 1
destroy

Why is the value undef being assigned to the variable before setting
it to 2? Surely C<local $x = 2> should set the value in one go,
without going through undef first.

�local� is a can of worms that nobody wants to touch, because it is so hard to fix anything. See #119683, for instance.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Dec 2, 2014

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

@p5pRT
Copy link
Author

p5pRT commented Dec 2, 2014

From @epa

You seem to be implying that the behaviour of first assigning undef and then
afterwards the initializer value is specific to localized tied variables -
so an ordinary localized scalar doesn't have this wasted assignment.

If so, it could just be noted in the documentation that for reasons of
implementation convenience, tied localized variables get this funny effect.

About #119683, at first glance it appears that one should just forbid
localizing punctuation variables, with a short list of explicitly allowed
exceptions such as $_.

--
Ed Avis <eda@​waniasset.com>

@p5pRT
Copy link
Author

p5pRT commented Dec 2, 2014

From @cpansprout

On Tue Dec 02 09​:08​:37 2014, eda@​waniasset.com wrote​:

You seem to be implying that the behaviour of first assigning undef and then
afterwards the initializer value is specific to localized tied variables -
so an ordinary localized scalar doesn't have this wasted assignment.

I don�t mean to imply anything more than this is a very fuzzy area and may not get much attention. And also the behaviour is likely to change in future versions if we do ever get localisation straightened out.

If so, it could just be noted in the documentation that for reasons of
implementation convenience, tied localized variables get this funny effect.

About #119683, at first glance it appears that one should just forbid
localizing punctuation variables, with a short list of explicitly allowed
exceptions such as $_.

But you have to be able to localise $!.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Dec 2, 2014

From @epa

Ah... I wasn't aware that localizing $! was good practice. I assumed that $! is only set immediately after certain builtins (those calling libc functions that set errno) and outside of that all bets are off. The same would apply to $1 only being meaningful straight after a regexp match, with no third-party code in the meantime.

______________________________________________________________________
This email has been scanned by the Symantec Email Security.cloud service.
For more information please visit http​://www.symanteccloud.com
______________________________________________________________________

@p5pRT
Copy link
Author

p5pRT commented Dec 2, 2014

From @Leont

On Tue, Dec 2, 2014 at 3​:19 PM, Ed Avis <perlbug-followup@​perl.org> wrote​:

The documentation of local() in perlsub says

The argument list may be assigned to if desired\, which allows
you to initialize your local variables\.  \(If no initializer is
given for a particular variable\, it is created with an
undefined value\.\)

This led me to believe that

local $x = 5;

would initialize $x with the value 5; that is, save the old value of
$x on a hidden stack and then assign 5 to it. That should differ from

local $x;
$x = 5;

which saves the value of $x, sets $x to undef, and then in the next
statement assigns 5 to it. But in practice it appears that the two do
the same thing​:

\#\!/usr/bin/perl
use strict;
use warnings;
use 5\.018;
our $VERSION = '0\.0';
package NewScalar;
require Tie&#8203;::Scalar;
our @&#8203;ISA = qw\(Tie&#8203;::Scalar\);
sub FETCH \{ $\{$\_\[0\]\} \}
sub TIESCALAR \{
    my $t; return bless \\$t\, 'NewScalar';
\}
sub STORE \{ say 'store '\, $\_\[1\] // 'undef'; $\{$\_\[0\]\} = $\_\[1\] \}
sub DESTROY \{ say 'destroy' \}
package main;
our $x;
tie $x\, 'NewScalar' or die;
$x = 1;
\{ local $x = 2 \}

Here I expected to see

store 1    \# first assignment
store 2    \# initialization with local
store 1    \# put back the old value on exiting block
destroy

but instead the output is

store 1
store undef
store 2
store 1
destroy

Why is the value undef being assigned to the variable before setting
it to 2? Surely C<local $x = 2> should set the value in one go,
without going through undef first.

I have hit this too, causing a race condition. I would love to see this
fixed, but I'm not sure how much work would be involved in that.

Leon

@p5pRT
Copy link
Author

p5pRT commented Dec 2, 2014

From @exodist

Test​::Builder localises $!, $@​, and %sig stuff a LOT, and many many things
depend on it. Just to give an example.

On Tue, Dec 2, 2014, 1​:42 PM Ed Avis <eda@​waniasset.com> wrote​:

Ah... I wasn't aware that localizing $! was good practice. I assumed that
$! is only set immediately after certain builtins (those calling libc
functions that set errno) and outside of that all bets are off. The same
would apply to $1 only being meaningful straight after a regexp match, with
no third-party code in the meantime.

______________________________________________________________________
This email has been scanned by the Symantec Email Security.cloud service.
For more information please visit http​://www.symanteccloud.com
______________________________________________________________________

@p5pRT
Copy link
Author

p5pRT commented Dec 2, 2014

From @Leont

On Tue, Dec 2, 2014 at 10​:42 PM, Ed Avis <eda@​waniasset.com> wrote​:

Ah... I wasn't aware that localizing $! was good practice. I assumed that
$! is only set immediately after certain builtins (those calling libc
functions that set errno) and outside of that all bets are off. The same
would apply to $1 only being meaningful straight after a regexp match, with
no third-party code in the meantime.

It's fairly essential in for example a signal handler, because otherwise $!
values will seem to appear out of nowhere.

Leon

@p5pRT
Copy link
Author

p5pRT commented Dec 2, 2014

From @epa

Yes, I see the issue with signal handlers setting $!. Innocent code might hit a race with

  $ok = close $fh;
  # signal handler runs here
  die $! if not $ok;

and then the wrong error would be reported. One way out might be to make $! in effect lexically scoped, so it always refers to the errno set by the system call occurring immediately before in the program text (each call to a $!-setting builtin, then, would have a hidden my-variable storing its errno result). Then localizing it would be unnecessary and could become a no-op. This would mean that user code can no longer use $! to signal errors to its caller.

______________________________________________________________________
This email has been scanned by the Symantec Email Security.cloud service.
For more information please visit http​://www.symanteccloud.com
______________________________________________________________________

@p5pRT
Copy link
Author

p5pRT commented Dec 3, 2014

From cm.perl@abtela.com

Le 02/12/2014 22​:42, Ed Avis a écrit :

Ah... I wasn't aware that localizing $! was good practice.

Localizing $! (and $^E) has also proved necessary to allow reporting a
problem using Carp (really longmess/shortmess), see #81586 and #116118

I assumed that $! is only set immediately after certain builtins
(those calling libc functions that set errno) and outside of that all
bets are off. The same would apply to $1 only being meaningful straight
after a regexp match, with no third-party code in the meantime.

see also File​::Copy for direct manipulations of $! and $^E, and
win32/win32.c for setting $! from $^E (e.g. #119857).

@p5pRT
Copy link
Author

p5pRT commented Dec 3, 2014

From @epa

Yes, the File​::Copy error reporting interface seems like a bit of a misdesign with the benefit of hindsight.

______________________________________________________________________
This email has been scanned by the Symantec Email Security.cloud service.
For more information please visit http​://www.symanteccloud.com
______________________________________________________________________

@p5pRT
Copy link
Author

p5pRT commented Dec 3, 2014

From @iabyn

On Tue, Dec 02, 2014 at 06​:19​:28AM -0800, Ed Avis wrote​:

This led me to believe that

local $x = 5;

would initialize $x with the value 5; that is, save the old value of
$x on a hidden stack and then assign 5 to it. That should differ from

local $x;
$x = 5;

which saves the value of $x, sets $x to undef, and then in the next
statement assigns 5 to it. But in practice it appears that the two do
the same thing​:

No, it doesn't save the *value*, it saves the *container*.
For example,

  $x = 1;
  $ra = \$x;
  local $x = 2;
  print "$$ra\n"; # prints 1

The action of local has to be to create a new, undef SV and insert it
in the appropriate slot in the GV (or array or whatever, e.g. local
$a[0]). A later assign then sets that new SV to a particular value.
When you add tie() to the mix, you start to see some artifacts as a
consequence.

--
A walk of a thousand miles begins with a single step...
then continues for another 1,999,999 or so.

@p5pRT
Copy link
Author

p5pRT commented Dec 3, 2014

From @epa

Dave Mitchell wrote​:

No, it doesn't save the *value*, it saves the *container*.
For example,

$x = 1;
$ra = \$x;
local $x = 2;
print "$$ra\n"; # prints 1

This makes sense but it implies that it would be impossible to localize a tied scalar?
The newly created SV would have no relationship to the original tied one.
But it appears that somehow perl keeps the tying​: using the same NewScalar package
as earlier in this bug report,

  our $x;
  tie $x, 'NewScalar' or die;
  $x = 1;
  my $ra = \$x;
  local $x = 2;
  print "$$ra\n"; # prints 2

It looks like there may be some conceptual muddling. Normally you localize the symbol table
entry, giving it a fresh scalar; except when the existing entry was a tied scalar, in which case
perl pretends that local() is meant to work by assigning a temporary value. Is that correct?

Conceivably, local() could be split into localalias(), which always makes a new symbol table
entry (losing any tying that was going on), and localvalue(), which works via assignment.

--
Ed Avis <eda@​waniasset.com>

______________________________________________________________________
This email has been scanned by the Symantec Email Security.cloud service.
For more information please visit http​://www.symanteccloud.com
______________________________________________________________________

@p5pRT
Copy link
Author

p5pRT commented Dec 3, 2014

From @Abigail

On Tue, Dec 02, 2014 at 05​:07​:52PM +0000, Ed Avis wrote​:

You seem to be implying that the behaviour of first assigning undef and then
afterwards the initializer value is specific to localized tied variables -
so an ordinary localized scalar doesn't have this wasted assignment.

If so, it could just be noted in the documentation that for reasons of
implementation convenience, tied localized variables get this funny effect.

About #119683, at first glance it appears that one should just forbid
localizing punctuation variables, with a short list of explicitly allowed
exceptions such as $_.

localizing punctuation variables accounts for about 98% of my uses
of local. The other 2% go to "local $hash {key}" and "local $array [index]".

The 2% is optimistic, it's likely to be lower than that.

Abigail

@p5pRT
Copy link
Author

p5pRT commented Dec 3, 2014

From @Leont

On Wed, Dec 3, 2014 at 12​:39 PM, Ed Avis <eda@​waniasset.com> wrote​:

This makes sense but it implies that it would be impossible to localize a
tied scalar?
The newly created SV would have no relationship to the original tied one.
But it appears that somehow perl keeps the tying​: using the same NewScalar
package
as earlier in this bug report,

Magic explicitly supports copying (or not) the magic to the new temporary
value.

our $x;
tie $x\, 'NewScalar' or die;
$x = 1;
my $ra = \\$x;
local $x = 2;
print "$$ra\\n"; \# prints 2

It looks like there may be some conceptual muddling. Normally you
localize the symbol table
entry, giving it a fresh scalar; except when the existing entry was a tied
scalar, in which case
perl pretends that local() is meant to work by assigning a temporary
value. Is that correct?

Conceivably, local() could be split into localalias(), which always makes
a new symbol table
entry (losing any tying that was going on), and localvalue(), which works
via assignment.

In case of ties, they will still share the tied object though, which makes
the above point a bit moot.

Leon

@p5pRT
Copy link
Author

p5pRT commented Dec 3, 2014

From syber@crazypanda.ru

2014-12-03 14​:39 GMT+03​:00 Ed Avis <eda@​waniasset.com>​:

Dave Mitchell wrote​:

No, it doesn't save the *value*, it saves the *container*.
For example,

$x = 1;
$ra = \$x;
local $x = 2;
print "$$ra\n"; # prints 1

This makes sense but it implies that it would be impossible to localize a tied scalar?
The newly created SV would have no relationship to the original tied one.
But it appears that somehow perl keeps the tying​: using the same NewScalar package
as earlier in this bug report,

our $x;
tie $x\, 'NewScalar' or die;
$x = 1;
my $ra = \\$x;
local $x = 2;
print "$$ra\\n"; \# prints 2

It looks like there may be some conceptual muddling. Normally you localize the symbol table
entry, giving it a fresh scalar; except when the existing entry was a tied scalar, in which case
perl pretends that local() is meant to work by assigning a temporary value. Is that correct?

Keep in mind that any object is a scalar reference (RV) to a blessed SV.
In your case, 'local' creates new reference to the same object

Conceivably, local() could be split into localalias(), which always makes a new symbol table
entry (losing any tying that was going on), and localvalue(), which works via assignment.

--
Ed Avis <eda@​waniasset.com>

______________________________________________________________________
This email has been scanned by the Symantec Email Security.cloud service.
For more information please visit http​://www.symanteccloud.com
______________________________________________________________________

--
Oleg Pronin,
CTO, Co-Founder,
Crazy Panda LTD
CP Decision LTD

@p5pRT
Copy link
Author

p5pRT commented Dec 3, 2014

From @jandubois

On Wed, Dec 3, 2014 at 9​:09 AM, Leon Timmermans <fawaka@​gmail.com> wrote​:

On Wed, Dec 3, 2014 at 12​:39 PM, Ed Avis <eda@​waniasset.com> wrote​:

Conceivably, local() could be split into localalias(), which always makes
a new symbol table
entry (losing any tying that was going on), and localvalue(), which works
via assignment.

In case of ties, they will still share the tied object though, which makes
the above point a bit moot.

There is some code in Perl that is supposed to prevent the
intermediate assignment of undef to magical scalars. It was originally
added by Chip to prevent `local $SIG{...} = ...` letting signals slip
through when the handler was undef before the new value was assigned​:

  https://rt.perl.org//Public/Bug/Display.html?id=60360
  http​://perl5.git.perl.org/perl.git/commit/9711599

There is a comment in the original bug report why the patch only fixes
localization of tied hash elements and slices, but not array elements
or scalars​:

  https://rt.perl.org/Public/Bug/Display.html?id=60360#txn-493526

Cheers,
-Jan

@p5pRT
Copy link
Author

p5pRT commented Dec 3, 2014

From @epa

Thanks all for your explanations. So, although local works by making a new
symbol table entry, if the old entry had tie magic then this is copied to
the new, making it look more like an assignment (from the point of view of
the underlying tie class). This implies that a 'no-op' tied scalar is not
possible. Tie​::StdScalar will always have slightly different semantics to
an ordinary scalar because it localizes differently.

--
Ed Avis <eda@​waniasset.com>

@p5pRT
Copy link
Author

p5pRT commented Dec 3, 2014

From @Leont

On Wed, Dec 3, 2014 at 10​:34 PM, Ed Avis <eda@​waniasset.com> wrote​:

Thanks all for your explanations. So, although local works by making a new
symbol table entry, if the old entry had tie magic then this is copied to
the new, making it look more like an assignment (from the point of view of
the underlying tie class). This implies that a 'no-op' tied scalar is not
possible. Tie​::StdScalar will always have slightly different semantics to
an ordinary scalar because it localizes differently.

Actually, this problem may be fixable by adding a LOCALIZE method to the
tie interface that can return a new tie-object.

Leon

@p5pRT
Copy link
Author

p5pRT commented Dec 4, 2014

From @cpansprout

On Wed Dec 03 13​:45​:35 2014, LeonT wrote​:

On Wed, Dec 3, 2014 at 10​:34 PM, Ed Avis <eda@​waniasset.com> wrote​:

Thanks all for your explanations. So, although local works by making
a new
symbol table entry, if the old entry had tie magic then this is
copied to
the new, making it look more like an assignment (from the point of
view of
the underlying tie class). This implies that a 'no-op' tied scalar
is not
possible. Tie​::StdScalar will always have slightly different
semantics to
an ordinary scalar because it localizes differently.

Actually, this problem may be fixable by adding a LOCALIZE method to
the
tie interface that can return a new tie-object.

I think that�s a good idea, but it should be called LOCAL after the keyword that invokes it.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Dec 6, 2014

From @rjbs

* Father Chrysostomos via RT <perlbug-followup@​perl.org> [2014-12-03T21​:07​:59]

On Wed Dec 03 13​:45​:35 2014, LeonT wrote​:

Actually, this problem may be fixable by adding a LOCALIZE method to the
tie interface that can return a new tie-object.

I think that�s a good idea, but it should be called LOCAL after the keyword
that invokes it.

That sounds useful, and I agree on the name.

--
rjbs
from the bus

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

2 participants