Req #75179 [NEW]: Remove undocumented assignment operator precedence change
| From: | codedokode at gmail dot com | Date: | Sun, 10 Sep 2017 11:44:34 +0000 |
| Subject: | Req #75179 [NEW]: Remove undocumented assignment operator precedence change | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-211023@lists.php.net to get a copy of this message | ||
From: codedokode at gmail dot com
Operating system: Windows XP
PHP version: Irrelevant
Package: Scripting Engine problem
Bug Type: Feature/Change Request
Bug description:Remove undocumented assignment operator precedence change
Description:
------------
Accidently I found out that PHP allows ambiguous expressions like this:
$a + $b = 1;
Documentation states that plus operator has higher precedence than
assignment operator (which is the case for similar expression $a = 1 +
2), therefore I expected the code to produce a syntax error, but there
were only warnings about undefined variables [1]
I googled around and found out that there are some undocumented hacks in
the parser that make it ignore operator precedence in assignment. They
are not documented, the documentation [2] only mentions that "Although =
has a lower precedence than most other operators, PHP will still allow
expressions similar to the following: if (!$a = foo()), in which case
the return value of foo() is put into $a.". There is no clear
description, what types of invalid expressions are allowed, and how they
are interpreted.
I also checked PHP language spec by Facebook [3] and didn't found there
anything about this feature. I understand that is a third-party
specification but there seems to be no any other specifications.
I found several bugs where a similar question was asked: bug #17386, bug
#63825, bug #40820. It looks like PHP tries to "guess" author's intent
and "fix" the code. In all those bugs PHP developers confirmed that this
behaviour was intended.
As it turned out, PHP can also change precedence even in expressions
without assignment operator: bug #73802
I think this is wrong because:
- the rules for changing precedence are not documented, it is unclear
what result the code will produce.
- there are alternative PHP implementations (like HHVM) that will
probably not support this transformation, therefore the same code might
work differently in different PHP implementations.
- PHP is unable to guess author's original intent and producing a clear
syntax error message will help author to find the reason of error faster
rather than pretending that the code is correct and confusing the
author
- when static analysis tools find expression like $a + $b = 1, they
cannot state that this is a mistake because this code in fact works
For example, I saw a code where the author thought that assignment
target is written on the right and wrote a line like $a + $b = $c. PHP
interpreted the expression as ($a + ($b = $c)) but the original intent
was $c = $a + $b. We see that the "fix" by PHP parser only have confused
the author and a syntax error message would be much more useful in this
case.
The use cases where this behaviour might be useful like if (!$a = fn()),
are rare.
My suggestions are:
- admit that the parser is unable to guess author's original intent and
this behaviour is undesirable in future versions of PHP
- add a warning or deprecation notice when precedence is changed by the
parser with clear description of the problem
- remove precedence changing in some future PHP version and produce
syntax errors
If we don't start producing warnings, authors will continue to write
such code and even many years later PHP developers (and maybe developers
of alternative implementations) will have to support this undocumented
feature.
If necessary, I could try to make the pull request myself, but later
when I have time for this.
This bug can be assigned a low priority.
[1] https://3v4l.org/ATpvW
[2] http://php.net/manual/en/language.operators.precedence.php
[3]
https://github.com/php/php-langspec/blob/master/spec/10-expressions.md#assignment-operators
Test script:
---------------
<?php
// https://3v4l.org/ATpvW
$a + $b = 1;
Expected result:
----------------
Syntax error
Actual result:
--------------
No syntax error
--
Edit bug report at https://bugs.php.net/bug.php?id=75179&edit=1
--
Try a snapshot (PHP 5.4): https://bugs.php.net/fix.php?id=75179&r=trysnapshot54
Try a snapshot (PHP 5.5): https://bugs.php.net/fix.php?id=75179&r=trysnapshot55
Try a snapshot (trunk): https://bugs.php.net/fix.php?id=75179&r=trysnapshottrunk
Fixed in SVN: https://bugs.php.net/fix.php?id=75179&r=fixed
Fixed in release: https://bugs.php.net/fix.php?id=75179&r=alreadyfixed
Need backtrace: https://bugs.php.net/fix.php?id=75179&r=needtrace
Need Reproduce Script: https://bugs.php.net/fix.php?id=75179&r=needscript
Try newer version: https://bugs.php.net/fix.php?id=75179&r=oldversion
Not developer issue: https://bugs.php.net/fix.php?id=75179&r=support
Expected behavior: https://bugs.php.net/fix.php?id=75179&r=notwrong
Not enough info: https://bugs.php.net/fix.php?id=75179&r=notenoughinfo
Submitted twice: https://bugs.php.net/fix.php?id=75179&r=submittedtwice
register_globals: https://bugs.php.net/fix.php?id=75179&r=globals
PHP 4 support discontinued: https://bugs.php.net/fix.php?id=75179&r=php4
Daylight Savings: https://bugs.php.net/fix.php?id=75179&r=dst
IIS Stability: https://bugs.php.net/fix.php?id=75179&r=isapi
Install GNU Sed: https://bugs.php.net/fix.php?id=75179&r=gnused
Floating point limitations: https://bugs.php.net/fix.php?id=75179&r=float
No Zend Extensions: https://bugs.php.net/fix.php?id=75179&r=nozend
MySQL Configuration Error: https://bugs.php.net/fix.php?id=75179&r=mysqlcfg