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

Variable "$x" is not available triggered by lexical subs #15471

Open
p5pRT opened this issue Jul 23, 2016 · 8 comments
Open

Variable "$x" is not available triggered by lexical subs #15471

p5pRT opened this issue Jul 23, 2016 · 8 comments

Comments

@p5pRT
Copy link

p5pRT commented Jul 23, 2016

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

Searchable as RT128709$

@p5pRT
Copy link
Author

p5pRT commented Jul 23, 2016

From @mauke

Created by @mauke

$ perl -wE 'use experimental "lexical_subs"; my sub foo; sub bar { my ($x) = @​_; sub foo { $x } }'
Variable "$x" is not available.

According to perldoc perldiag, 'Variable "%s" is not available' only happens
with anonymous outer subs or string eval. This code uses neither.

Perl Info

Flags:
    category=core
    severity=low

Site configuration information for perl 5.24.0:

Configured by mauke at Mon May  9 21:21:33 CEST 2016.

Summary of my perl5 (revision 5 version 24 subversion 0) configuration:
   
  Platform:
    osname=linux, osvers=4.4.5-1-arch, archname=i686-linux
    uname='linux simplicio 4.4.5-1-arch #1 smp preempt thu mar 10 07:54:30 cet 2016 i686 gnulinux '
    config_args=''
    hint=previous, useposix=true, d_sigaction=define
    useithreads=undef, usemultiplicity=undef
    use64bitint=undef, use64bitall=undef, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2 -flto',
    cppflags='-fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include'
    ccversion='', gccversion='6.1.1 20160501', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234, doublekind=3
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12, longdblkind=3
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=4, prototype=define
  Linker and Libraries:
    ld='cc', ldflags ='-fstack-protector-strong -L/usr/local/lib -flto'
    libpth=/usr/local/lib /usr/lib/gcc/i686-pc-linux-gnu/6.1.1/include-fixed /usr/lib /lib /usr/local/lib /usr/lib/gcc/i686-pc-linux-gnu/6.1.1/include-fixed /usr/lib
    libs=-lpthread -lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lc -lgdbm_compat
    perllibs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
    libc=libc-2.23.so, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version='2.23'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -O2 -flto -L/usr/local/lib -fstack-protector-strong'



@INC for perl 5.24.0:
    /home/mauke/usr/lib/perl5/site_perl/5.24.0/i686-linux
    /home/mauke/usr/lib/perl5/site_perl/5.24.0
    /home/mauke/usr/lib/perl5/5.24.0/i686-linux
    /home/mauke/usr/lib/perl5/5.24.0
    .


Environment for perl 5.24.0:
    HOME=/home/mauke
    LANG=en_US.UTF-8
    LANGUAGE=en_US
    LC_COLLATE=C
    LC_MONETARY=de_DE.UTF-8
    LC_TIME=de_DE.UTF-8
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/mauke/perl5/perlbrew/bin:/home/mauke/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl
    PERLBREW_BASHRC_VERSION=0.73
    PERLBREW_HOME=/home/mauke/.perlbrew
    PERLBREW_ROOT=/home/mauke/perl5/perlbrew
    PERL_BADLANG (unset)
    PERL_UNICODE=SAL
    SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Jul 24, 2016

From @cpansprout

On Sat Jul 23 15​:29​:46 2016, mauke- wrote​:

$ perl -wE 'use experimental "lexical_subs"; my sub foo; sub bar { my
($x) = @​_; sub foo { $x } }'
Variable "$x" is not available.

According to perldoc perldiag, 'Variable "%s" is not available' only
happens
with anonymous outer subs or string eval. This code uses neither.

Should it be producing that warning, or should it producing this one?

$ ./perl -Ilib -wE 'sub bar { my ($x) = @​_; sub foo { $x } }'
Variable "$x" will not stay shared at -e line 1.

With regard to the implementation, lexical subs are comparable to this example given in perldiag​:

  sub f {
  my $a;
  sub { eval '$a' }
  }
  f()->();

Conceptually, they have more in common with the ‘not stay shared’ example.

Both of these warnings sort of fall out of the implementation, and are just there to warn the programmer that things may not behave as intended, for non-obvious reasons.

I’m ambivalent about how we should resolve this. Either we expand the ‘not available’ documentation in perldiag, or we change it to the other warning.

Which should it be?

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Jul 24, 2016

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

@p5pRT
Copy link
Author

p5pRT commented Jul 31, 2016

From @ap

* Father Chrysostomos via RT <perlbug-followup@​perl.org> [2016-07-24 07​:24]​:

I’m ambivalent about how we should resolve this. Either we expand the
‘not available’ documentation in perldiag, or we change it to the
other warning.

As I understand the “not available” warning, it really only talks about
the “not available *any more*” case, whereas lexical subs present a “not
available *yet*” situation. I am not certain that internals-wise this is
strictly the same situation as “will not stay shared”, but to the extent
that I understand it, the ramifications for the user are the same.

If I am correct then I say it ought to warn “will not stay shared”.

Regards,
--
Aristotle Pagaltzis // <http​://plasmasturm.org/>

@p5pRT
Copy link
Author

p5pRT commented Jul 31, 2016

From @cpansprout

On Sat Jul 30 20​:46​:25 2016, aristotle wrote​:

* Father Chrysostomos via RT <perlbug-followup@​perl.org> [2016-07-24 07​:24]​:

I’m ambivalent about how we should resolve this. Either we expand the
‘not available’ documentation in perldiag, or we change it to the
other warning.

As I understand the “not available” warning, it really only talks about
the “not available *any more*” case, whereas lexical subs present a “not
available *yet*” situation.

It can mean ‘not available ever’​:

sub {
  my $x;
  sub foo {
  $x
  }
};

‘Is not available’ means ‘we are creating a sub right now, but we can’t get the value from that outside variable.’ (Though, come to think of it, ‘will not stay shared’ means the same thing. Maybe I should actually look at the code, instead of waving my hands so frantically. :-)

I am not certain that internals-wise this is
strictly the same situation as “will not stay shared”, but to the extent
that I understand it, the ramifications for the user are the same.

Those last eight words were want I wanted to hear.

If I am correct then I say it ought to warn “will not stay shared”.

Based on your feedback, I agree. Thank you.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Aug 4, 2016

From @iabyn

On Sat, Jul 30, 2016 at 11​:15​:43PM -0700, Father Chrysostomos via RT wrote​:

On Sat Jul 30 20​:46​:25 2016, aristotle wrote​:

* Father Chrysostomos via RT <perlbug-followup@​perl.org> [2016-07-24 07​:24]​:

I’m ambivalent about how we should resolve this. Either we expand the
‘not available’ documentation in perldiag, or we change it to the
other warning.

As I understand the “not available” warning, it really only talks about
the “not available *any more*” case, whereas lexical subs present a “not
available *yet*” situation.

It can mean ‘not available ever’​:

sub {
my $x;
sub foo {
$x
}
};

‘Is not available’ means ‘we are creating a sub right now, but we can’t get the value from that outside variable.’ (Though, come to think of it, ‘will not stay shared’ means the same thing.

'not available' and 'not stay shared' are two different things. This​:

  sub bar {
  my ($x) = @​_;
  sub foo { $x }
  printf "x=%s foo=%s\n", $x, foo();
  }

  bar(1);
  bar(2);

gives​:

  Variable "$x" will not stay shared at /home/davem/tmp/p line 7.
  x=1 foo=1
  x=2 foo=1

i.e. the $x captured by foo() always remains as the first instance of
bar's $x - the one that exists from bar being created through to the
first exit from a call to bar().

Prepending this to the above example​:

  my sub foo;

gives​:

  Variable "$x" is not available.
  x=1 foo=
  x=2 foo=

I don't know enough of the details of lexical vars to know whether that's
expected behaviour, but its certainly *different* behaviour and is thus
deserving of a different warning message.

--
More than any other time in history, mankind faces a crossroads. One path
leads to despair and utter hopelessness. The other, to total extinction.
Let us pray we have the wisdom to choose correctly.
  -- Woody Allen

@p5pRT
Copy link
Author

p5pRT commented Aug 7, 2016

From @cpansprout

On Thu Aug 04 04​:07​:17 2016, davem wrote​:

'not available' and 'not stay shared' are two different things. This​:

sub bar {
my ($x) = @​_;
sub foo { $x }
printf "x=%s foo=%s\n", $x, foo();
}

bar(1);
bar(2);

gives​:

Variable "$x" will not stay shared at /home/davem/tmp/p line 7.
x=1 foo=1
x=2 foo=1

i.e. the $x captured by foo() always remains as the first instance of
bar's $x - the one that exists from bar being created through to the
first exit from a call to bar().

Prepending this to the above example​:

my sub foo;

gives​:

Variable "$x" is not available.
x=1 foo=
x=2 foo=

I don't know enough of the details of lexical vars to know whether
that's
expected behaviour, but its certainly *different* behaviour and is
thus
deserving of a different warning message.

I am slightly surprised that the output is different. It may even be a bug, but in such areas the implementation usually gets to decide the correct behaviour.

‘my’ subs are cloned when the scope in which the declaration occurs is entered. So the lexical sub case is similar to the package sub case, in that the inner sub is created before the outer sub is called.

But ‘my’ subs follow a different code path (the same code that clones anonymous subs) from package subs.

So now the question is whether those code paths should be doing the same thing.

As usual, I’m too lazy to look at the code right now, so this conversation will probably go nowhere, at least for the time being.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Aug 8, 2016

From @iabyn

On Sat, Aug 06, 2016 at 07​:45​:22PM -0700, Father Chrysostomos via RT wrote​:

On Thu Aug 04 04​:07​:17 2016, davem wrote​:

'not available' and 'not stay shared' are two different things. This​:

sub bar {
my ($x) = @​_;
sub foo { $x }
printf "x=%s foo=%s\n", $x, foo();
}

bar(1);
bar(2);

gives​:

Variable "$x" will not stay shared at /home/davem/tmp/p line 7.
x=1 foo=1
x=2 foo=1

i.e. the $x captured by foo() always remains as the first instance of
bar's $x - the one that exists from bar being created through to the
first exit from a call to bar().

Prepending this to the above example​:

my sub foo;

gives​:

Variable "$x" is not available.
x=1 foo=
x=2 foo=

I don't know enough of the details of lexical vars to know whether
that's
expected behaviour, but its certainly *different* behaviour and is
thus
deserving of a different warning message.

I am slightly surprised that the output is different. It may even be a bug, but in such areas the implementation usually gets to decide the correct behaviour.

‘my’ subs are cloned when the scope in which the declaration occurs is entered. So the lexical sub case is similar to the package sub case, in that the inner sub is created before the outer sub is called.

But ‘my’ subs follow a different code path (the same code that clones anonymous subs) from package subs.

So now the question is whether those code paths should be doing the same thing

Ok, given that foo is cloned near the start of execution, after bar
has been created (so the first instance of $x exists), I would expect
it to behave similar to to the non-lexical case. So this whiffs of a bug.

--
You never really learn to swear until you learn to drive.

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