rfc:zpp-conversion-rules

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
rfc:zpp-conversion-rules [2015/02/19 03:16] francoisrfc:zpp-conversion-rules [2021/03/27 14:25] (current) – Move to inactive ilutov
Line 1: Line 1:
-====== PHP RFC: Type parsing restrictions ====== +====== PHP RFC: Type parsing modifications ====== 
-  * Version: 0.1 +  * Version: 0.4 
-  * Date: 2015-02-19+  * Date: 2015-02-22
   * Author: François Laupretre, francois@php.net   * Author: François Laupretre, francois@php.net
-  * Status: Draft+  * Status: Inactive
   * First Published at: https://wiki.php.net/rfc/zpp-conversion-rules   * First Published at: https://wiki.php.net/rfc/zpp-conversion-rules
  
Line 9: Line 9:
 ===== Introduction ===== ===== Introduction =====
  
-This RFC proposes to implement a new set of rules to be used when parsing +This RFC proposes changes in the ruleset used to filter 
-internal function arguments.+and convert input arguments to internal functions. 
 + 
 +===== History =====
  
 The changes proposed here are based on concerns that arose during the discussion about The changes proposed here are based on concerns that arose during the discussion about
 [[https://wiki.php.net/rfc/scalar_type_hints|scalar type hints]]. [[https://wiki.php.net/rfc/scalar_type_hints|scalar type hints]].
  
-While the discussion focused on a dual-mode approach, with people opposing use cases +While the discussion mostly opposed 'weak' and 'strict' mode proponents, 
-about so-called 'weak' and 'strict' typingsome of us decided to search for +each camp showing use cases to prove it was right, we decided to gather all these use cases 
-a compromise that would satisfy both camps+and go exploring another way : search a single-mode compromise that would satisfy both camps. 
- +
-It was soon clear that the biggest argument of strict-type proponents was that +
-'weak' mode was way too permissive, +
-allowing, for instance, ((bool)true) or '7 years' as integer value.+
  
-As the proposed argument type hinting mechanism is aligned on the ZPP behavior, +It was soon clear that the strongest argument of strict-typing proponents was that 
-and as everyone agreed it should remain so, it was decided to propose a new more +'weak' mode was way too permissive, allowing, for instance, true or '7 years' as integer value.
-restrictive ruleset to be implemented in ZPP and zend_parse_parameters().+
  
-Sothis RFC presents a new ruleset for parameter parsing and implicit conversions.+As the 'weak' mode of the proposed type hinting mechanism was based on the ZPP layer, 
 +and as everyone agreed any single-mode mechanism should keep using it, 
 +we decided to propose a new more restrictive ruleset to be implemented in ZPP.
  
-Note: In the rest of the document, 'ZPP' means 'Z_PARAM macros and zend_parse_parameters()' +Note: In the whole document, we use the 'ZPP' term as a union set including Z_PARAM macros, zend_parse_arg_xxx() functions, and zend_parse_parameters() 
-as, whatever the final implementationboth mechanisms must remain in sync.+as, whatever the rulesetthese mechanisms must keep implementing the same logic.
  
 ===== Proposal ===== ===== Proposal =====
Line 36: Line 35:
 ==== Current ruleset ==== ==== Current ruleset ====
  
-The ZPP ruleset does not authorizes implicit conversions for the IS_NULL, IS_FALSE,+The ZPP ruleset authorizes implicit conversions for IS_NULL, IS_FALSE,
 IS_TRUE, IS_LONG, IS_DOUBLE, and IS_STRING zval types only. IS_TRUE, IS_LONG, IS_DOUBLE, and IS_STRING zval types only.
  
-Actually, it also implement a mechanism for (object -> string) but, as this mechanism+Actually, it also implement a mechanism for (object -> string) but, as this one
 will remain unchanged, it will be ignored here. will remain unchanged, it will be ignored here.
  
-This table shows the current rules to accept and convert an input zval through +The following table shows the current rules used to accept and convert an input zval through 
-the ZPP layer. It also shows the resulting values when fixed :+ZPP :
  
 ^            ^  Zval type  ^^^^^^^^ ^            ^  Zval type  ^^^^^^^^
 ^  ZPP type  ^ IS_NULL        ^ IS_FALSE     ^ IS_TRUE      ^ IS_LONG   ^ IS_DOUBLE ^ IS_STRING ^ ^  ZPP type  ^ IS_NULL        ^ IS_FALSE     ^ IS_TRUE      ^ IS_LONG   ^ IS_DOUBLE ^ IS_STRING ^
 ^ bool       | Yes (-> false) | <native>     | <native>     | Yes (1)   | Yes (1)   | Yes (2)   | ^ bool       | Yes (-> false) | <native>     | <native>     | Yes (1)   | Yes (1)   | Yes (2)   |
-^ long       | Yes (-> 0)     | Yes (-> 0)   | Yes (-> 1)   | <native>  | Yes       | (3)       |+^ long       | Yes (-> 0)     | Yes (-> 0)   | Yes (-> 1)   | <native>  | Yes (5)   | (3)       |
 ^ double     | Yes (-> 0.0)   | Yes (-> 0.0) | Yes (-> 1.0) | Yes       | <native>  | (4)       | ^ double     | Yes (-> 0.0)   | Yes (-> 0.0) | Yes (-> 1.0) | Yes       | <native>  | (4)       |
 ^ string     | Yes (-> ""   | Yes (-> "" | Yes (-> "1") | Yes       | Yes       | <native>  | ^ string     | Yes (-> ""   | Yes (-> "" | Yes (-> "1") | Yes       | Yes       | <native>  |
Line 56: Line 55:
   * (3) Run string through is_numeric_str_function() and detect error. If double returned, convert it to long   * (3) Run string through is_numeric_str_function() and detect error. If double returned, convert it to long
   * (4) Run string through is_numeric_str_function() and detect error. If int returned, convert it to double   * (4) Run string through is_numeric_str_function() and detect error. If int returned, convert it to double
 +  * (5) Discard fractional part, if any
  
-The conversion of IS_STRING to int/float is doing so though _is_numeric_string_ex().+The conversion of IS_STRING to int/float is done through _is_numeric_string_ex().
 Among others, this function has the following behavior : Among others, this function has the following behavior :
  
-  * Stop conversion at first non digit character with no error +  * Stop conversion at first non digit character with no error (ignore every trailing char).
- +
-Note: this is what authorizes '7 years' as integer.+
  
 ==== Proposed changes ==== ==== Proposed changes ====
  
-  * Disable IS_FALSE/IS_NULL to anything but bool (native)+  * Disable IS_FALSE/IS_NULL to anything except bool. 
-  * Disable (IS_STRING -> bool) +  * IS_STRING to bool: Convert every string that would be converted to 0 or 0.0 to false, instead of just “0”. 
-  * Disable IS_NULL conversion to every ZPP type. It causes IS_NULL to be systematically rejected by every Z_PARAM macro except Z_PARAM_ZVAL.+  * Disable IS_NULL to be accepted for any ZPP type except the new 'null'.
   * Disable (IS_DOUBLE -> long) if the fractional part of the input value is non null.   * Disable (IS_DOUBLE -> long) if the fractional part of the input value is non null.
   * When converting from IS_STRING to long, reject conversion if string contains the representation of a number with a non null fractional part.   * When converting from IS_STRING to long, reject conversion if string contains the representation of a number with a non null fractional part.
 +  * Add a 'null' ZPP type. This type accepts IS_NULL only. While quite useless for input arguments, it is used as return type and as element of union types.
  
-In is_numeric_str_function() :+In _is_numeric_string_ex() :
  
   * Add a check for trailing characters : trailing blanks are accepted, the first non-blank character encountered raises an error (note that blanks are supported as leading or trailing chars only).   * Add a check for trailing characters : trailing blanks are accepted, the first non-blank character encountered raises an error (note that blanks are supported as leading or trailing chars only).
Line 81: Line 80:
  
 ^            ^  Zval type  ^^^^^^^^ ^            ^  Zval type  ^^^^^^^^
-^  ZPP type     ^ IS_NULL ^ IS_FALSE ^ IS_TRUE  ^ IS_LONG   ^ IS_DOUBLE ^  IS_STRING ^ +^  ZPP type     ^ IS_NULL  ^ IS_FALSE ^ IS_TRUE  ^ IS_LONG   ^ IS_DOUBLE ^  IS_STRING ^ 
-^ bool          |  -      | <native> | <native> | Yes (1)    Yes (1)   |  -        +^ null          | <native> |  -       | -        | -          -        | -         | 
-^ long          |  -      |  -        -       | <native>  |  (2)       |  (3)      | +^ bool          |  -       | <native> | <native> | Yes (1)    Yes (1)  |  Yes (5)  
-^ double        |  -      |  -        -       | Yes       | <native>   |  (4)      | +^ long          |  -       |  -        -       | <native>  |  (2)      |  (3)      | 
-^ string        |  -      |  -        -       | Yes        Yes       | <native>  |+^ double        |  -       |  -        -       | Yes       | <native>  |  (4)      | 
 +^ string        |  -       |  -        -       | Yes        Yes      | <native>  |
  
   * (1) false if null, true if non null   * (1) false if null, true if non null
Line 91: Line 91:
   * (3) Run string through is_numeric_str_function() and detect error. If double with null fractional part returned, convert to long, else error   * (3) Run string through is_numeric_str_function() and detect error. If double with null fractional part returned, convert to long, else error
   * (4) Run string through is_numeric_str_function() and detect error. If int returned, convert to double   * (4) Run string through is_numeric_str_function() and detect error. If int returned, convert to double
 +  * (5) If string is numeric and contains a representation of a null number (anything that would convert to 0 or 0.0), or if string is empty, -> false, otherwise -> true.
  
 and the new behavior of _is_numeric_string_ex() : and the new behavior of _is_numeric_string_ex() :
Line 99: Line 100:
 ===== Backward Incompatible Changes ===== ===== Backward Incompatible Changes =====
  
-Every restriction of the ruleset cause a BC break.+Every change we propose here is a BC break.
  
 ===== Proposed PHP Version(s) ===== ===== Proposed PHP Version(s) =====
  
-Because of BC breaks, requires a major version.+7.0.
  
 ===== RFC Impact ===== ===== RFC Impact =====
Line 110: Line 111:
  
 Any code converting a string to a number is potentially impacted. If this cause Any code converting a string to a number is potentially impacted. If this cause
-an unacceptable BC break, we'll create a private copy of this function specific +an unacceptable BC break, we'll create a private copy of the function implemeneting 
-for argument parsing. As long as it is not needed, it is better if every string to +(string -> int/float) and will reserve it for ZPP. As long as it is not clearly needed, 
-numeric conversion uses the same code.+we'll keep a common code for every string to number conversions in PHP.
  
 ==== To Opcache ==== ==== To Opcache ====
Line 123: Line 124:
  
 ==== php.ini Defaults ==== ==== php.ini Defaults ====
- 
-None 
  
 ===== Open Issues ===== ===== Open Issues =====
- 
-Coming soon... 
  
 ===== Unaffected PHP Functionality ===== ===== Unaffected PHP Functionality =====
Line 134: Line 131:
 ===== Future Scope ===== ===== Future Scope =====
  
-The set of supported numeric strings can be extended. +String to numeric conversion can be improved and accept a richer syntax.
- +
-String to numeric conversion can be made smarter and accept more.+
  
 ===== Proposed Voting Choices ===== ===== Proposed Voting Choices =====
rfc/zpp-conversion-rules.1424315795.txt.gz · Last modified: 2017/09/22 13:28 (external edit)