This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #86136] Downgrade sort {my $a} to a warning
authorFather Chrysostomos <sprout@cpan.org>
Wed, 4 Jul 2012 04:34:59 +0000 (21:34 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Wed, 4 Jul 2012 04:40:59 +0000 (21:40 -0700)
commit271c8bde9d592c5e6bb98307158488ea8f751037
treed24f45281cd08e58c41a5daf31bc9a0c47550261
parent449d128bedd078da737396a9a10e07e1b3364beb
[perl #86136] Downgrade sort {my $a} to a warning

The code in toke.c for detecting lexical $a or $b used in a comparison
in a sort block was simply horrible.  If the last-used named list or
unary op (PL_last_lop_op) was sort, then it would scan for <=> or cmp
anywhere on the current line of code.  That meant that, although this
would die:

    my $a; sort { $a <=> $b } ()

This would do the wrong thing without complaint:

    my $a; sort { print; $a <=> $b } ()

And this would die, completely gratuitously:

    my $a; sort @t; $a + $cmp;

Since perl is only guessing that lexical $a or $b *might* have
been used accidentally, this should be a warning, and certainly
not an error.

Also, scanning the source code like that for <=> (even inside a
string!) can never work.  One would have to parse it and examine the
resulting op tree.

In fact, since we *are* parsing it anyway, we *can* examine
the op tree.

So that’s exactly what this commit does.  Based on the existing behav-
iour, but with far fewer false positives, it checks for a cmp or <=>
op as the last statement of a sort block and warns about any operand
that is a lexical $a or $b.
op.c
pod/perldiag.pod
t/lib/warnings/op
toke.c