rfc:integer_semantics

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Next revisionBoth sides next revision
rfc:integer_semantics [2014/08/19 19:12] ajfrfc:integer_semantics [2014/09/14 22:46] – v0.2.2 - Added examples ajf
Line 1: Line 1:
 ====== PHP RFC: Integer Semantics ====== ====== PHP RFC: Integer Semantics ======
-  * Version: 0.1.1+  * Version: 0.2.2
   * Date: 2014-08-19   * Date: 2014-08-19
   * Author: Andrea Faulds <ajf@ajf.me>   * Author: Andrea Faulds <ajf@ajf.me>
-  * Status: Draft+  * Status: In Voting
   * First Published at: http://wiki.php.net/rfc/integer_semantics   * First Published at: http://wiki.php.net/rfc/integer_semantics
  
Line 15: Line 15:
  
   - Instead of being undefined and platform-dependant, NaN and Infinity will always be zero when casted to integer   - 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 +  - Bitwise shifts by negative numbers of bits will be disallowed (throws ''E_WARNING'' and gives ''FALSE'', like a division by zero) 
-  - 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 +  - Left bitwise shifts by a number of bits beyond the bit width of an integer will always result in 0, even on CPUs which wrap around 
-  - Float values outside of the range of an integer (PHP_INT_MIN <= $x <= PHP_INT_MAXpassed to functions expecting integers will raise an E_WARNING and make zend_parse_parameters fail (usually making the function bail out and return NULL)+  - Right bitwise shifts 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 
 + 
 +==== Examples ==== 
 + 
 +For all "was" results, these are only on my machine, as they would differ across platforms. All "now" results are the same on all platforms. 
 + 
 +<code php> 
 +// Was: int(-9223372036854775808) 
 +// Now: int(0) 
 +var_dump((int)NAN); 
 +// Was: int(-9223372036854775808) 
 +// Now: int(0) 
 +var_dump((int)INF); 
 +// Was: int(4611686018427387904) 
 +// Now: bool(false) and E_WARNING 
 +var_dump(1 << -2)
 +// Was: int(8) 
 +// Now: int(0) 
 +var_dump(8 >> 64); 
 +</code>
  
 ===== Rationale ===== ===== Rationale =====
Line 25: Line 44:
 "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. "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.+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'' is effectively ''>> 1''). To ensure cross-platform consistency, we ensure that such shifts shifts will always result in zero (for left shifts), or zero or negative one (for right shifts, depending on the sign of the number being shifted). It is worth noting that shifts of a number of bits greater than the bit width of an integer is also undefined behaviour in C.
  
 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 (''-9223372036854775808''). 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 (''-9223372036854775808'').
  
-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 [[rfc:bigint|Big Integer Support]] RFC. Alongside cleaning up some aspects of how integers work, this RFC partly paves the way for bigints. This RFC also helps clear up some undefined behaviour in the PHP specification by explicitly defining it.
- +
-The changes in this RFC are all backported from my [[rfc:bigint|Big Integer Support]] RFC. Alongside cleaning up some aspects of how integers work, this RFC paves the way for bigints.+
  
 ===== Proposed PHP Version(s) ===== ===== Proposed PHP Version(s) =====
Line 37: Line 54:
 The next major release of PHP, currently PHP 7. The next major release of PHP, currently PHP 7.
  
-===== Open Issues/Future Scope =====+===== Unaffected PHP Functionality =====
  
-Do I need to make left shifts also consistently do the same thing when shifted by a number greater than the bit width? believe Intel CPUs cause problems for such shifts also.+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 have not affected how they deal with strings as they didn't in the first place (they cast to integer)This does not touch the behaviour of array key casting (except for Infinity and NaN), although this is something I would like to do
  
-===== Unaffected PHP Functionality =====+===== Open Questions/Possible Future Scope =====
  
-Integer to float conversion is untouched. Despite some people's misconceptionsthe 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 arraysalthough this is something I would like to do+Currently PHP throws an ''E_WARNING'' and gives ''FALSE'' for a division by zeroand under this RFC, so would shifts by negative countsWhile not strictly an //integer// semantics issue, should we make division by zero result in Infinity/-Infinity per IEEE 754, and perhaps make it throw no error, or an E_NOTICE? If we did thatshould we make this return NaN instead?
  
 ===== Proposed Voting Choices ===== ===== Proposed Voting Choices =====
  
-This is a "language change", arguably, so it requires a 2/3 majority. A straight Yes/No vote would be held.+This is a language change, so it requires a 2/3 majority. A straight Yes/No vote would be held.
  
 ===== Patches and Tests ===== ===== Patches and Tests =====
  
-work-in-progress patch is here: https://github.com/TazeTSchnitzel/php-src/compare/php:master...TazeTSchnitzel:integer_semantics+pull request is here: https://github.com/php/php-src/pull/781
  
-It is nearly finished, and only needs certain broken tests to be updated.+The patch is working and has tests, but code review would be appreciated.
  
 ===== Implementation ===== ===== Implementation =====
Line 60: Line 77:
   - a link to the git commit(s)   - a link to the git commit(s)
   - a link to the PHP manual entry for the feature   - a link to the PHP manual entry for the feature
 +
 +===== Vote =====
 +
 +As this is a language change, a 2/3 majority is required.
 +
 +Voting started 2014-09-14 and ends 2014-09-21.
 +
 +<doodle title="Accept the integer semantics RFC and merge patch into master?" auth="ajf" voteType="single" closed="false">
 +   * Yes
 +   * No
 +</doodle>
  
 ===== References ===== ===== References =====
Line 70: Line 98:
 ===== Changelog ===== ===== Changelog =====
  
 +  * v0.2.2 - Added examples
 +  * v0.2.1 - Open Questions/Possible Future Scope added
 +  * v0.2 - Dropped zend_parse_parameters change, fixed left shift too
   * v0.1.1 - Introduction added   * v0.1.1 - Introduction added
   * v0.1 - Initial version   * v0.1 - Initial version
rfc/integer_semantics.txt · Last modified: 2017/09/22 13:28 by 127.0.0.1