-
Notifications
You must be signed in to change notification settings - Fork 561
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
"Possible precedence problem between ! and numeric eq (==)" failure in automake #22954
Comments
You can also reproduce this by pulling the latest automake code, building it and running automake.
|
If it is intended for The purpose of the warning is to call out a common mistake where !$x == $y is written instead of !($x == $y) - but warnings just produce STDERR output, is it causing some other issue? |
Yes, in automake case it's causing automake to exit with rc of 255
|
Ah they have: |
Using fatal warnings is an assumption of risk of breakage: https://perldoc.perl.org/warnings#Fatal-Warnings |
This code is bizarre. It uses That is, my $neg = $1 eq '!';
my $val = transform_token($token, $transform, $2) ? 1 : 0;
return ($val == $neg) ? '##%' : ''; would do the right thing and not trigger a warning. (Alternatively, parenthesizing the last expression as That said, the warning already has a list of exceptions where it doesn't trigger:
It would be fairly easy to add |
I think that would risk failing to catch instances where !!($x == $y) was accidentally written without the parentheses, as that is rather similar to the original case it is meant to catch, and that exception should only be added if automake isn't reasonably able to work around the warning; and if that is the case, they should be strongly recommended not to use fatal warnings as this issue will occur again. |
I'm also seeing a similar case in texinfo (another GNU package):
/home/itodoro/zopen/usr/local/zopen/texinfo/texinfo/share/texinfo/Texinfo/Convert/Converter.pm line 1092.
/home/itodoro/zopen/usr/local/zopen/texinfo/texinfo/share/texinfo/Texinfo/Convert/Info.pm line 92.
|
Curl fails at
|
I have sent an email to |
These are actual logical errors which the warning has pointed out; the code is attempting to check whether |
Should these warnings have been introduced in a minor or major release rather than a patch release? 5.41.3 did not emit these warnings. I've seen 3 popular open source tools break as a result of these changes. |
As mentioned, these warnings emit only STDERR in supported operation. If these utilities are using fatal warnings, they have accepted the contract that they must update their code whenever new warnings are introduced. This allows new warnings to be introduced, as otherwise Perl's devotion to backwards compatibility would make it near impossible to do so, major version or not. In addition, this is not a patch release, this is a development release. These warnings will not be introduced to a stable version of Perl until 5.42.0. |
Ok, thanks I have reported the issue to the curl community: curl/curl#16128 |
On Thu, 30 Jan 2025, 07:13 mauke, ***@***.***> wrote:
my $neg = ($1 eq '!') ? 1 : 0;my $val = transform_token($token, $transform, $2);return (!!$val == $neg) ? '##%' : '';
This code is bizarre.
I dont agree it's bizarre. The ternary is superluous, but it's not that
weird or unusual for people to write code like this in the interest of
clarity.
It would be fairly easy to add !!... == ... (double negation on LHS) to the
list of exceptions. Is this something we want?
Imo yes. !!$x is a standard "operator" to booleanify a var. (Book published
a huge list of such "operators" years ago.) Using it with == should not be
a warning.
I've written code like this many many many times, I would be rather annoyed
if they started warning. It's a very common idiom in certain situations.
Cheers
Yves
|
So is !, and adding that exception would make this warning do nothing, so I don't agree with this logic. |
My issue is not that the ternary is superfluous. It's that they go out of their way to manually convert a boolean to an integer in one case If they had used To put it another way, one side of the equation is natively a boolean ( (Also, I'm not familiar with the context of the code, but boolifying a string treats |
On Thu, 30 Jan 2025, 14:38 Dan, ***@***.***> wrote:
On Thu, 30 Jan 2025, 07:13 mauke, *@*.***> wrote:
my $neg = ($1 eq '!') ? 1 : 0;my $val = transform_token($token,
$transform, $2);return (!!$val == $neg) ? '##%' : '';
This code is bizarre.
I dont agree it's bizarre. The ternary is superluous, but it's not that
weird or unusual for people to write code like this in the interest of
clarity.
It would be fairly easy to add !!... == ... (double negation on LHS) to the
list of exceptions. Is this something we want?
Imo yes. !!$x is a standard "operator" to booleanify a var. (Book published
a huge list of such "operators" years ago.) Using it with == should not be
a warning.
So is !, and adding that exception would make this warning do nothing, so
I don't agree with this logic.
I dont think the two cases are the same. Double bang is a long established
way to do something that is commonly used in many contexts and expresses a
specific intent that is hard to mistake and really has no other clean way
to do anyway. Single bang may or may not be intended so at least the
warning has some utility. I'd say 99.9999% of the time this warning fires
for double bang it will be a false positive. That is annoying, not helpful.
This kind of "change your code because we don't approve of your coding
style" is something we long avoided, I dont see why that should change
now. I'd rather see this warning removed if we are going to break common
idioms like this that people have been using for decades.
Yves
|
On Thu, 30 Jan 2025, 14:48 mauke, ***@***.***> wrote:
I dont agree it's bizarre. The ternary is superluous, but it's not that
weird or unusual for people to write code like this in the interest of
clarity.
My issue is not that the ternary is superfluous. It's that they go out of
their way to manually convert a boolean to an integer in one case ($1 eq
'!') ? 1 : 0, but in the other case they simply slap a !! on the variable
and call it a day.
I dont really get how your point is not about the ternary being
superfluous. You just complained that they used ternary in one case but not
the other. I've seen less experienced devs do this kind of thing with
inequalities and complex expressions, and ive seen experienced devs do this
so that less experienced devs understood the intent. Bang bang on the other
hand is long established idiom and imo "not" (no matter howyou spell it)
always returns a boolean.
I've also seen this kind of thing on codebases where different skilled devs
have worked on the code over time. The less experienced puts the ternary
in, and the more experienced doesn't bother.
Either way imo it's not bizarre. Maybe a touch unidiomatic, but pretty par
for the course in a mixed skill level workforce codebase.
Another reason I have seen the ternary form used is when someone
inexperienced wanted to debug the result of the expression by using
interpolation. A bool false in string form is the empty string, which makes
it "invisible' in interpolated form. Using the ternary is a perfectly
reasonable way to ensure it was visible in a diagnostic. Maybe after they
finished debugging they deleted the diagnostic but left the ternary
"because it works".
These things happen all the time, not everybody has the time or passion to
ensure they are using the most idiomatic code, they just want something
that works. Larry is on record as deliberately wanting people to be able to
write baby talk perl as well as academic perl. Imo this is a perfect
example.
If they had used ? 1 : 0 consistently on both sides (using == to compare
two integers), they wouldn't get a warning. If they had used !!
consistently on both sides (using == to implicitly numify the booleans),
they wouldn't get a warning.
Seems to me you are making assumptions here, for instance that this cide
was written by one person in a single edit pass.
If this was the result of multiple devs working on the code over time it
would be quite understandable. The beginner used the ternary not really
knowing better, the more experienced dev added the idiomatic bang bang but
chose not to change the unidiomatic but functionally correct code that used
the ternary on the grounds of "if isn't broken dont fix it".
TIMTOWTDI.
I bet if Graham or Book did a search of their work code they'd find dozens
of cases like this, if not more.
To put it another way, one side of the equation is natively a boolean ($1
eq '!'), the other a string (transform_token(...)). Those are different
types and some people like to be explicit about type conversions, sure. But
here the first value is explicitly converted from a boolean to an integer,
and the second value from a string to a boolean. In the end, we still have
different types and must rely on == to perform an implicit conversion.
This feels bizarre to me and I don't see how doing things this way makes
anything clearer.
I'd agree the pure idiomatic form is clearer. But that isn't really
relevant, the code is still functionally correct , false is silently
equivalent to 0 in numeric context.
I've seen code like this many many times, it really isn't that weird when
you beginners and more experienced devs work together.
(Also, I'm not familiar with the context of the code, but boolifying a
string treats '0' and '' as the same value. I'm not sure if this is
intentional.
IMO people that write bang bang certainly want that behavior, otherwise
they wouldn't use it.
Yves
… |
Content Warning: Light hearted pedantry The word "regression" in the title of this ticket is not appropriate to the situation. This is a new (fatal) warning from a new version of perl. So, gression-wise, I'd say it's progression, not regression. |
tp/Texinfo/Convert/LaTeX.pm (output), tp/Texinfo/Convert/IXIN.pm: fix precedence problem between ! and string eq, which leads to a warning with Perl 5.41.7. Report from Igor Todorovski, details on: Perl/perl5#22954 (comment)
I agree. Generally speaking false positives we really want to avoid in warnings. It doesn't take that many for people to turn that warning off, and then we're in an even worse position. |
I have some thoughts.
On the whole, I'll err on the side of caution and prepare a patch that exempts The warning itself should stay, I think. It has identified real bugs in high-profile projects such as perl's Test2 suite, texinfo, and curl. |
Exempt `!!` from the "Possible precedence problem between ! and <cmp>" warning. Fixes Perl#22954.
+1 to what @mauke said (and not just because he used one of my modules as a counterexample ;) ) The new warning is providing valuable feedback on genuinely suspect code. The false positives are an annoying distraction to it, which the PR fixes (and I have reviewed and given it a thumbs up). Also agree that anyone running fatalized warnings in a production system is skating on very thin ice. They have asked for their code to randomly start crashing out on warnings from future versions of Perl, so that is what they shall receive. |
On Fri, 31 Jan 2025, 15:31 mauke, ***@***.***> wrote:
I have some thoughts.
-
Fatalizing all warnings is a bad idea; doing so in production code is
just asking for trouble. That's automake's problem.
Agreed
- However, there is a more general issue here. I agree that false
positives are bad in general and should be avoided where reasonably
possible.
Agreed.
-
Only the automake case is a false positive. The texinfo and curl cases
are true positives: The warning has found real bugs.
-
I tried to search CPAN for instances of !! being used in suspicious
ways. I only found two results:
- Alien::Build::Plugin::Fetch::Git
<https://metacpan.org/release/PLICEASE/Alien-Build-Git-0.10/source/lib/Alien/Build/Plugin/Fetch/Git.pm#L150>:
$can_minus_c = !! $? == 0 && -d $tmp->child('.git');
I'm not sure what's going on here. You could call this a false
positive because the code produces correct results, but !! $? == 0
leaves me scratching my head. I can't tell what the author's intent was and
I think the !! should just be removed.
I guess the code is intended to handle $? Being 0 and $? being undef but
it isn't obvious to me why it is not just !$?. Assuming $? can be undef i
can imagine someone at 3am doing this, even if I wouldn't.
-
- Device::BusPirate::Mode::SPI
<https://metacpan.org/release/PEVANS/Device-BusPirate-0.25/source/lib/Device/BusPirate/Mode/SPI.pm#L183>:
if( any { defined $args{$_} and !!$args{$_} != $self->$_ } qw( open_drain ckp cke sample ) ) {
This is a genuine false positive. Avoiding the warning would be
simple (by writing $args{$_} ^^ $self->$_ or !!$args{$_} !=
!!$self->$_ or (!!$args{$_}) != $self->$_), but I count it as a
point towards making !! exempt from the warning.
If you have more examples, please let me know.
Did you look at test code perchance?
-
As for the automake code not being bizarre: I don't follow Yves'
reasoning. Sure, I can see how code might end up in this shape due to
inattention or multiple developers of different experience levels working
on it, but that wasn't the point. The point is that the end result is
incoherent code.
We are quibbling over what constitutes bizarre, which IMO is just fine.
I'm in Asia right now and they eat things for breakfast that people in
Europe would consider bizarre and vice-versa. Bizarre isn't an objectively
verifiable attribute, it's a matter of personal opinion.
As for incoherent, I'll still disagree. I certainly agree that it is not
idiomatic Perl code, but I don't expect idiomatic perl code from most devs
and Larry didn't want the language restricted to people who know the idioms
(which i suspect have evolved over time).
-
As for treating '0' and '' as the same value being intentional because
otherwise people wouldn't write !! in their code: I don't buy it.
People write sloppy code all the time.
People write correct code all the time too. Every time I used bang bang I
very much wanted all true values collapsed to a single value and I wanted
all false values collapsed to a single value (even if that value was a
dual-var like PL_sv_no).
-
That doesn't mean they fully understand the ramifications of writing a
check a particular way. (For example, the texinfo case above doesn't use
!!, but it is a bug that doesn't let you use 0 as the output filename.)
Not sure it is reasonable to use one bug to argue that people using a
different construct dont know what they are doing.
-
This kind of "change your code because we don't approve of your coding
style" is something we long avoided, I dont see why that should change
now.
That ... is not something I would agree with. Consider this warning
from perl 4.0.33:
$ perl -wE 'say (":-)");'
say (...) interpreted as function at -e line 1.
:-)
Or this one from perl 5.000:
$ perl -we 'use Carp qw(croak); exec "echo ok"; croak "Could not exec: $!"'
Statement unlikely to be reached at -e line 1.
(Maybe you meant system() when you said exec()?)
ok
Or these from perl 5.003_08:
$ perl -we 'my @c = qw( ! ? . , ; # );'
Possible attempt to separate words with commas at -e line 1.
Possible attempt to put comments in qw() list at -e line 1.
These are all false positives, enforcing a particular "coding style".
(In particular, the qw ones have always annoyed me. They've never
identified a single bug in my code. Can we patch them out?)
I wouldn't object.
-
On the whole, I'll err on the side of caution and prepare a patch that
exempts !! from the warning because of code like the one in
Device::BusPirate. (More examples welcome.)
Thank you.
The warning itself should stay, I think. It has identified real bugs in
high-profile projects such as perl's Test2 suite, texinfo, and curl.
Fwiw (not much really) i don't have a problem with the warning provided it
has the right exemptions. My comment was purely about !!$x == ...
Thanks again for your efforts.
Yves
|
Per Perl recommendation: https://perldoc.perl.org/warnings#Fatal-Warnings Suggested by Collin Funk: https://lists.gnu.org/archive/html/automake/2025-01/msg00003.html And in the Perl discussion: Perl/perl5#22954 (comment) * bin/aclocal.in: just use warnings, not making them fatal. * bin/automake.in: * contrib/tap-driver.pl: * gen-testsuite-part: * lib/Automake/ChannelDefs.pm: * lib/Automake/Channels.pm: * lib/Automake/Condition.pm: * lib/Automake/Config.in: * lib/Automake/Configure_ac.pm: * lib/Automake/DisjConditions.pm: * lib/Automake/FileUtils.pm: * lib/Automake/General.pm: * lib/Automake/Getopt.pm: * lib/Automake/Item.pm: * lib/Automake/ItemDef.pm: * lib/Automake/Language.pm: * lib/Automake/Location.pm: * lib/Automake/Options.pm: * lib/Automake/Rule.pm: * lib/Automake/RuleDef.pm: * lib/Automake/VarDef.pm: * lib/Automake/Variable.pm: * lib/Automake/Version.pm: * lib/Automake/Wrap.pm: * lib/Automake/XFile.pm: * t/ax/deltree.pl: * t/ax/extract-testsuite-summary.pl: * t/check-fd-redirect.sh: * t/tap-signal.tap: * t/tests-environment-fd-redirect.sh: * t/testsuite-summary-count-many.sh:
Module:
Description
When using Perl 5.41.7 or Perl 5.41.8, we are seeing this error message appear when running automake (written in perl).
Perl 5.41.3 did not have this problem.
Is this expected? It's preventing us from building autotools based projects.
Here's the reduced snippet of what automake is doing:
Steps to Reproduce
Expected behavior
No "Possible precedence problem between ! and numeric eq (==)" message
Perl configuration
The text was updated successfully, but these errors were encountered: