This is an old revision of the document!
PHP RFC: Integer Semantics
This RFC improves cross-platform consistency in PHP for some operations dealing with integers, and makes PHP's behaviour more intuitive, as well as partly paving the way for Big Integer Support.
This RFC proposes changes to certain behaviours related to integers:
- Instead of being undefined and platform-dependant, NaN and Infinity will always be zero when casted to integer
- Bitwise shifts by negative numbers of bit will be disallowed
- A right bitwise shift by a number of bits beyond the bit width of an integer will always result in 0 or -1 (depending on sign), even on CPUs which wrap around
- Float values outside of the range of an integer (PHP_INT_MIN <= $x <= PHP_INT_MAX) passed to functions expecting integers will raise an E_WARNING and make zend_parse_parameters fail (usually making the function bail out and return NULL)
This RFC tries to clean up some integer edge cases and make integers more consistent across platforms. As PHP is a high-level language, we ought to abstract away implementation differences, otherwise we make it difficult to write code that runs consistently across platforms, something which is an key requirement for PHP.
“Negative shifts” do not do what users would reasonably expect them to do: shift in the opposite direction. Rather, a negative shift is usually a shift by the 2's complement unsigned integer representation (in the case of
-2, this would be
18446744073709551614 when integers are 64-bit). This is also reliant on undefined behaviour in C, and will give different results depending on the processor and integer size. For this reason, we now disallow such shifts.
On Intel CPUs, a bitwise shift by a number of bits that is greater than the bit width of an integer (e.g.
>> 65 on a 64-bit machine) will “wrap around” (e.g.
>> 65 would become
1). To ensure cross-platform consistency, we ensure that right shifts will always result in zero or negative one (depending on the sign of the number being shifted) in this case.
Making NaN and Infinity always become zero when casted to integer means more cross-platform consistency, and is also less surprising than what is currently produces, where NaN produces the minimum integer on my machine (
Finally, we make float values outside of the range of an integer cause zend_parse_parameters to fail and raise an E_WARNING when an integer was expected. This is likely to reduce bugs, as currently, float values which are too large will silently overflow, which I expect is probably not what users expect. For the rare use case where an overflow is desired, an explicit integer cast would always always possible.
The changes in this RFC are all backported from my Big Integer Support RFC. Alongside cleaning up some aspects of how integers work, this RFC paves the way for bigints.
Proposed PHP Version(s)
The next major release of PHP, currently PHP 7.
Open Issues/Future Scope
Do I need to make left shifts also consistently do the same thing when shifted by a number greater than the bit width? I believe Intel CPUs cause problems for such shifts also.
Unaffected PHP Functionality
Integer to float conversion is untouched. Despite some people's misconceptions, the bitwise shift operators do not operate on strings like the other bitwise operators do, so I have not affected how they deal with strings as they didn't in the first place (they cast to integer). This does not touch arrays, although this is something I would like to do
Proposed Voting Choices
This is a “language change”, arguably, so it requires a 2/3 majority. A straight Yes/No vote would be held.
Patches and Tests
A work-in-progress patch is here: https://github.com/TazeTSchnitzel/php-src/compare/php:master...TazeTSchnitzel:integer_semantics
It is nearly finished, and only needs certain broken tests to be updated.
After the project is implemented, this section should contain
- the version(s) it was merged to
- a link to the git commit(s)
- a link to the PHP manual entry for the feature
Keep this updated with features that were discussed on the mail lists.
- v0.1.1 - Introduction added
- v0.1 - Initial version