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

perl mistakenly warns when $] indexes a slice #12256

Closed
p5pRT opened this issue Jul 7, 2012 · 15 comments
Closed

perl mistakenly warns when $] indexes a slice #12256

p5pRT opened this issue Jul 7, 2012 · 15 comments

Comments

@p5pRT
Copy link

p5pRT commented Jul 7, 2012

Migrated from rt.perl.org#114024 (status was 'resolved')

Searchable as RT114024$

@p5pRT
Copy link
Author

p5pRT commented Jul 7, 2012

From lponeil@math.umd.edu

Created by lponeil@math.umd.edu

Hey Perl folks.

The following code dies, but shouldn't.

  use warnings FATAL => 'all';
  my @​a = 0..9; print @​a[$],0];

Larry.

Perl Info

Flags:
    category=core
    severity=low

Site configuration information for perl 5.14.2:

Configured by Debian Project at Fri Mar 23 17:28:34 UTC 2012.

Summary of my perl5 (revision 5 version 14 subversion 2) configuration:

  Platform:
    osname=linux, osvers=2.6.24-31-server,
archname=i686-linux-gnu-thread-multi-64int
    uname='linux palmer 2.6.24-31-server #1 smp tue feb 14 14:08:16
utc 2012 i686 i686 i386 gnulinux '
    config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN
-Dcccdlflags=-fPIC -Darchname=i686-linux-gnu -Dprefix=/usr
-Dprivlib=/usr/share/perl/5.14 -Darchlib=/usr/lib/perl/5.14
-Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5
-Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local
-Dsitelib=/usr/local/share/perl/5.14.2
-Dsitearch=/usr/local/lib/perl/5.14.2 -Dman1dir=/usr/share/man/man1
-Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1
-Dsiteman3dir=/usr/local/man/man3 -Duse64bitint -Dman1ext=1
-Dman3ext=3perl -Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh
-Ud_ualarm -Uusesfio -Uusenm -Ui_libutil -DDEBUGGING=-g -Doptimize=-O2
-Duseshrplib -Dlibperl=libperl.so.5.14.2 -des'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=define, usemultiplicity=define
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=define, use64bitall=undef, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN
-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include
-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2 -g',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fno-strict-aliasing
-pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='4.6.3', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long long', ivsize=8, nvtype='double', nvsize=8,
Off_t='off_t', lseeksize=8
    alignbytes=4, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =' -fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /lib/i386-linux-gnu /lib/../lib
/usr/lib/i386-linux-gnu /usr/lib/../lib /lib /usr/lib
    libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt
    perllibs=-ldl -lm -lpthread -lc -lcrypt
    libc=, so=so, useshrplib=true, libperl=libperl.so.5.14.2
    gnulibc_version='2.15'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -O2 -g -L/usr/local/lib
-fstack-protector'

Locally applied patches:



@INC for perl 5.14.2:
    /etc/perl
    /usr/local/lib/perl/5.14.2
    /usr/local/share/perl/5.14.2
    /usr/lib/perl5
    /usr/share/perl5
    /usr/lib/perl/5.14
    /usr/share/perl/5.14
    /usr/local/lib/site_perl
    .


Environment for perl 5.14.2:
    HOME=/home/lponeil
    LANG=en_US.UTF-8
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
    PERL_BADLANG (unset)
    SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Jul 31, 2012

From @cpansprout

On Fri Jul 06 18​:01​:00 2012, lponeil@​math.umd.edu wrote​:

This is a bug report for perl from lponeil@​math.umd.edu,
generated with the help of perlbug 1.39 running under perl 5.14.2.

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

Hey Perl folks.

The following code dies, but shouldn't.

use warnings FATAL => 'all';
my @​a = 0\.\.9; print @​a\[$\]\,0\];

Larry.

Interesting​:

$ ./perl -Ilib -Mwarnings=syntax -e '@​a{$],0}'
Scalar value @​a{$] better written as $a{$] at -e line 1.

And​:

$ ./perl -Ilib -Mwarnings=syntax -e '@​a["]",0]'
Scalar value @​a["] better written as $a["] at -e line 1.
$ ./perl -Ilib -Mwarnings=syntax -e '@​a["}",0]'
Scalar value @​a["} better written as $a["} at -e line 1.

The code that produces this warning (case '@​' in toke.c​:yylex) scans the
source following the [ or { for zero or more of these​:

  alphanumerics space tab $ # + - ' "

followed by ] or }.

So it seems to be designed to catch​:

$a+1
-1
2
$#foo
--$_
$_++
'foo'
"foo"

But it also catches​:

foo # could be a function returning a list
$]
"]"
"}"
qw"foo bar" # see ticket #28380

but not ${]} (there is your workaround).

And warns for syntax errors (the syntax error is fine; the warning is
weird)​:

$ ./perl -Ilib -Mwarnings=syntax -e '@​a[]'
Scalar value @​a[] better written as $a[] at -e line 1.
syntax error at -e line 1, near "[]"
Execution of -e aborted due to compilation errors.

We could change it to skip the warning for the empty string or an
initial alphanumeric character. Instead of warning immediately, the
lexer could flag the op, and the compiler could then look to see whether
there is indeed just one kidop and warn.

I think that would work, without making the lexer’s heuristics overly
complex.

Is there anything obviously wrong with that?

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Jul 31, 2012

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

@p5pRT
Copy link
Author

p5pRT commented Aug 1, 2012

From @cpansprout

On Tue Jul 31 08​:55​:25 2012, sprout wrote​:

On Fri Jul 06 18​:01​:00 2012, lponeil@​math.umd.edu wrote​:

This is a bug report for perl from lponeil@​math.umd.edu,
generated with the help of perlbug 1.39 running under perl 5.14.2.

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

Hey Perl folks.

The following code dies, but shouldn't.

use warnings FATAL => 'all';
my @​a = 0\.\.9; print @​a\[$\]\,0\];

Larry.

Interesting​:

$ ./perl -Ilib -Mwarnings=syntax -e '@​a{$],0}'
Scalar value @​a{$] better written as $a{$] at -e line 1.

And​:

$ ./perl -Ilib -Mwarnings=syntax -e '@​a["]",0]'
Scalar value @​a["] better written as $a["] at -e line 1.
$ ./perl -Ilib -Mwarnings=syntax -e '@​a["}",0]'
Scalar value @​a["} better written as $a["} at -e line 1.

The code that produces this warning (case '@​' in toke.c​:yylex) scans the
source following the [ or { for zero or more of these​:

alphanumerics space tab $ \# \+ \- ' "

followed by ] or }.

So it seems to be designed to catch​:

$a+1
-1
2
$#foo
--$_
$_++
'foo'
"foo"

But it also catches​:

foo # could be a function returning a list
$]
"]"
"}"
qw"foo bar" # see ticket #28380

but not ${]} (there is your workaround).

And warns for syntax errors (the syntax error is fine; the warning is
weird)​:

$ ./perl -Ilib -Mwarnings=syntax -e '@​a[]'
Scalar value @​a[] better written as $a[] at -e line 1.
syntax error at -e line 1, near "[]"
Execution of -e aborted due to compilation errors.

We could change it to skip the warning for the empty string or an
initial alphanumeric character. Instead of warning immediately, the
lexer could flag the op, and the compiler could then look to see whether
there is indeed just one kidop and warn.

I think that would work, without making the lexer’s heuristics overly
complex.

Is there anything obviously wrong with that?

Yes​: the source code cannot easily be accessed once one has an op.

Would it be acceptable to change the warning to use an ellipsis?
(Scalar value @​a[...] better written as $a[...].)

Would it be acceptable to remove this warning altogether? The only case
that could cause a problem is @​a[+foo], because foo could be called
unexpectedly in list context. But that is precisely the case in which
perl cannot know that foo won’t return a list on purpose. @​a[0] is
generally harmless. Is this supposed to be newbie patrol (to stop them
from using @​a[0] all over the place)?

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Aug 1, 2012

From @lizmat

On Aug 1, 2012, at 8​:05 AM, Father Chrysostomos via RT wrote​:

On Tue Jul 31 08​:55​:25 2012, sprout wrote​:

$ ./perl -Ilib -Mwarnings=syntax -e '@​a[]'
Scalar value @​a[] better written as $a[] at -e line 1.
syntax error at -e line 1, near "[]"
Execution of -e aborted due to compilation errors.

We could change it to skip the warning for the empty string or an
initial alphanumeric character. Instead of warning immediately, the
lexer could flag the op, and the compiler could then look to see whether
there is indeed just one kidop and warn.

I think that would work, without making the lexer’s heuristics overly
complex.

Is there anything obviously wrong with that?
Yes​: the source code cannot easily be accessed once one has an op.

Would it be acceptable to change the warning to use an ellipsis?
(Scalar value @​a[...] better written as $a[...].)

Would it be acceptable to remove this warning altogether? The only case
that could cause a problem is @​a[+foo], because foo could be called
unexpectedly in list context. But that is precisely the case in which
perl cannot know that foo won’t return a list on purpose. @​a[0] is
generally harmless. Is this supposed to be newbie patrol (to stop them
from using @​a[0] all over the place)?

I wonder whether this warning shouldn't be removed on the grounds that​:

1. it is valid Perl 6 syntax, so what are we teaching newbies anyway?
2. there is only a performance difference between $a[0] and @​a[0], or am I missing something there?

Liz

@p5pRT
Copy link
Author

p5pRT commented Aug 1, 2012

From lponeil@math.umd.edu

Hello Father Chrysostomos.

making the lexer's heuristics overly complex.

My officemate just called this a "gross understatement", which i
thought you'd find amusing. :-). The bug report was academic and not
use-based, but i'll read your email in more detail and respond later.
Thanks.

Larry.

@p5pRT
Copy link
Author

p5pRT commented Aug 1, 2012

From @nwc10

On Wed, Aug 01, 2012 at 09​:31​:03AM +0200, Elizabeth Mattijsen wrote​:

I wonder whether this warning shouldn't be removed on the grounds that​:

1. it is valid Perl 6 syntax, so what are we teaching newbies anyway?

But it means something subtly different - there it's a regular lookup, here
it's a trivial slice. Although I'm not sure how often the difference matters.

I don't think we should use "it's legal Perl 6 syntax" alone as grounds for
changing Perl 5 behaviour. For example, the analogous hash lookup syntax
%h{"k"} isn't legal Perl 5.

I think that the George Bernard Shaw quote "England and America are two
countries separated by a common language." applies to Perl 5 and Perl 6,
but I'm not quite sure how to paraphrase it. In that there are massive
amount of similarities between the two, but you need to treat them as
different, else you get into embarrassing mistakes. (eg "rubber")

2. there is only a performance difference between $a[0] and @​a[0], or am I missing something there?

With a little bit of experimenting I did manage to find one difference​:

$ perl -le 'sub foo (\[$@​]) {}; foo $a[0]'
$ perl -le 'sub foo (\[$@​]) {}; foo @​a[0]'
Type of arg 1 to main​::foo must be one of [$@​] (not array slice) at -e line 1, at EOF
Execution of -e aborted due to compilation errors.
$

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Aug 1, 2012

From @cpansprout

On Wed Aug 01 10​:59​:45 2012, nicholas wrote​:

On Wed, Aug 01, 2012 at 09​:31​:03AM +0200, Elizabeth Mattijsen wrote​:

I wonder whether this warning shouldn't be removed on the grounds
that​:

1. it is valid Perl 6 syntax, so what are we teaching newbies
anyway?

But it means something subtly different - there it's a regular lookup,
here
it's a trivial slice. Although I'm not sure how often the difference
matters.

I don't think we should use "it's legal Perl 6 syntax" alone as
grounds for
changing Perl 5 behaviour. For example, the analogous hash lookup
syntax
%h{"k"} isn't legal Perl 5.

I think that the George Bernard Shaw quote "England and America are
two
countries separated by a common language." applies to Perl 5 and Perl
6,
but I'm not quite sure how to paraphrase it. In that there are massive
amount of similarities between the two, but you need to treat them as
different, else you get into embarrassing mistakes. (eg "rubber")

2. there is only a performance difference between $a[0] and @​a[0],
or am I missing something there?

With a little bit of experimenting I did manage to find one
difference​:

$ perl -le 'sub foo (\[$@​]) {}; foo $a[0]'
$ perl -le 'sub foo (\[$@​]) {}; foo @​a[0]'
Type of arg 1 to main​::foo must be one of [$@​] (not array slice) at -e
line 1, at EOF
Execution of -e aborted due to compilation errors.
$

The most significant different is, of course, assignment thereto. It
changes the context of the RHS. It is actually useful though, which is
probably why I usually find myself turning off syntax warnings​:

@​_[0] = /(.*)/

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Aug 1, 2012

From @lizmat

On Aug 1, 2012, at 7​:59 PM, Nicholas Clark wrote​:

On Wed, Aug 01, 2012 at 09​:31​:03AM +0200, Elizabeth Mattijsen wrote​:

I wonder whether this warning shouldn't be removed on the grounds that​:
1. it is valid Perl 6 syntax, so what are we teaching newbies anyway?

But it means something subtly different - there it's a regular lookup, here
it's a trivial slice. Although I'm not sure how often the difference matters.

I don't think we should use "it's legal Perl 6 syntax" alone as grounds for
changing Perl 5 behaviour. For example, the analogous hash lookup syntax
%h{"k"} isn't legal Perl 5.

Then maybe it should be. :-)

Seriously, from Perl trainers I've always understood that it is always the most difficult thing for newbies to grasp. Which is why Larry decided to stick with the sigil for the type of data structure, regardless of the access / context.

I think that the George Bernard Shaw quote "England and America are two
countries separated by a common language." applies to Perl 5 and Perl 6,
but I'm not quite sure how to paraphrase it. In that there are massive
amount of similarities between the two, but you need to treat them as
different, else you get into embarrassing mistakes. (eg "rubber")

And some of them you can't even express in writing. "You say potato, and I say potato". Gotcha.

2. there is only a performance difference between $a[0] and @​a[0], or am I missing something there?
With a little bit of experimenting I did manage to find one difference​:

$ perl -le 'sub foo (\[$@​]) {}; foo $a[0]'
$ perl -le 'sub foo (\[$@​]) {}; foo @​a[0]'
Type of arg 1 to main​::foo must be one of [$@​] (not array slice) at -e line 1, at EOF
Execution of -e aborted due to compilation errors.

Wow, that's pretty obscure. I guess you *could* argue that that's a bug, but I won't :-)

Liz

@p5pRT
Copy link
Author

p5pRT commented Aug 1, 2012

From @lizmat

On Aug 1, 2012, at 9​:49 PM, Father Chrysostomos via RT wrote​:

On Wed Aug 01 10​:59​:45 2012, nicholas wrote​:

On Wed, Aug 01, 2012 at 09​:31​:03AM +0200, Elizabeth Mattijsen wrote​:

I wonder whether this warning shouldn't be removed on the grounds
that​:

1. it is valid Perl 6 syntax, so what are we teaching newbies
anyway?

But it means something subtly different - there it's a regular lookup,
here
it's a trivial slice. Although I'm not sure how often the difference
matters.

I don't think we should use "it's legal Perl 6 syntax" alone as
grounds for
changing Perl 5 behaviour. For example, the analogous hash lookup
syntax
%h{"k"} isn't legal Perl 5.

I think that the George Bernard Shaw quote "England and America are
two
countries separated by a common language." applies to Perl 5 and Perl
6,
but I'm not quite sure how to paraphrase it. In that there are massive
amount of similarities between the two, but you need to treat them as
different, else you get into embarrassing mistakes. (eg "rubber")

2. there is only a performance difference between $a[0] and @​a[0],
or am I missing something there?

With a little bit of experimenting I did manage to find one
difference​:

$ perl -le 'sub foo (\[$@​]) {}; foo $a[0]'
$ perl -le 'sub foo (\[$@​]) {}; foo @​a[0]'
Type of arg 1 to main​::foo must be one of [$@​] (not array slice) at -e
line 1, at EOF
Execution of -e aborted due to compilation errors.
$

The most significant different is, of course, assignment thereto. It
changes the context of the RHS. It is actually useful though, which is
probably why I usually find myself turning off syntax warnings​:

@​_[0] = /(.*)/

Aw, evil! But yes, an idiom that would probably be much more prevalent than the prototype issue.

Liz

@p5pRT
Copy link
Author

p5pRT commented Aug 2, 2012

From @cpansprout

On Wed Aug 01 12​:57​:59 2012, elizabeth wrote​:

On Aug 1, 2012, at 9​:49 PM, Father Chrysostomos via RT wrote​:

On Wed Aug 01 10​:59​:45 2012, nicholas wrote​:

On Wed, Aug 01, 2012 at 09​:31​:03AM +0200, Elizabeth Mattijsen
wrote​:

I wonder whether this warning shouldn't be removed on the grounds
that​:

1. it is valid Perl 6 syntax, so what are we teaching newbies
anyway?

But it means something subtly different - there it's a regular
lookup,
here
it's a trivial slice. Although I'm not sure how often the
difference
matters.

I don't think we should use "it's legal Perl 6 syntax" alone as
grounds for
changing Perl 5 behaviour. For example, the analogous hash lookup
syntax
%h{"k"} isn't legal Perl 5.

I think that the George Bernard Shaw quote "England and America are
two
countries separated by a common language." applies to Perl 5 and
Perl
6,
but I'm not quite sure how to paraphrase it. In that there are
massive
amount of similarities between the two, but you need to treat them
as
different, else you get into embarrassing mistakes. (eg "rubber")

2. there is only a performance difference between $a[0] and @​a[0],
or am I missing something there?

With a little bit of experimenting I did manage to find one
difference​:

$ perl -le 'sub foo (\[$@​]) {}; foo $a[0]'
$ perl -le 'sub foo (\[$@​]) {}; foo @​a[0]'
Type of arg 1 to main​::foo must be one of [$@​] (not array slice) at
-e
line 1, at EOF
Execution of -e aborted due to compilation errors.
$

The most significant different is, of course, assignment thereto.
It
changes the context of the RHS. It is actually useful though, which
is
probably why I usually find myself turning off syntax warnings​:

@​_[0] = /(.*)/

Aw, evil! But yes, an idiom that would probably be much more
prevalent than the prototype issue.

... were it not for the silly warning!

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Aug 2, 2012

From @iabyn

On Wed, Aug 01, 2012 at 09​:54​:31PM +0200, Elizabeth Mattijsen wrote​:

With a little bit of experimenting I did manage to find one difference​:

$ perl -le 'sub foo (\[$@​]) {}; foo $a[0]'
$ perl -le 'sub foo (\[$@​]) {}; foo @​a[0]'
Type of arg 1 to main​::foo must be one of [$@​] (not array slice) at -e line 1, at EOF
Execution of -e aborted due to compilation errors.

Wow, that's pretty obscure. I guess you *could* argue that that's a bug, but I won't :-)

There's also a context difference in the way the indices are calculated​:

  sub f { print wantarray, "\n"; 0 }
  $a[f()] = 1;
  @​a[f()] = 1;

which gives

  $ ./perl /tmp/p

  1
  $

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

@p5pRT
Copy link
Author

p5pRT commented Sep 15, 2013

From @cpansprout

Fixed in 429a255.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Sep 15, 2013

From [Unknown Contact. See original ticket]

Fixed in 429a255.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Sep 15, 2013

@cpansprout - Status changed from 'open' to 'resolved'

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