rfc:strict_operators

Differences

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

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
rfc:strict_operators [2020/07/06 11:49]
jasny
rfc:strict_operators [2020/07/15 14:27] (current)
jasny
Line 1: Line 1:
 ====== PHP RFC: Strict operators directive ====== ====== PHP RFC: Strict operators directive ======
  
-  * Version: 1.4 +  * Version: 1.5 
-  * Date: 2020-06-09 (first version: 2019-05-25)+  * Date: 2020-07-06 (first version: 2019-05-25)
   * Author: Arnold Daniels, <jasny@php.net>   * Author: Arnold Daniels, <jasny@php.net>
-  * Status: Under Discussion+  * Status: Withdrawn
   * First Published at: http://wiki.php.net/rfc/strict_operators   * First Published at: http://wiki.php.net/rfc/strict_operators
  
 ===== Introduction ===== ===== Introduction =====
-https://gist.github.com/jasny/bfd711844a8876f8206ed21357e2e2da+
 The rules PHP uses for type juggling with operators are complex, varying by operator as well as the types and values of the operands. The rules PHP uses for type juggling with operators are complex, varying by operator as well as the types and values of the operands.
  
Line 23: Line 23:
 If strict_operators is enabled, the following stricter rules will be used; If strict_operators is enabled, the following stricter rules will be used;
  
-  * Operators may perform type casting, but not type juggling: +  * Operators may perform type conversion, but not type juggling: 
-    * Type casting is not based on the type of the other operand +    * Type conversion is not based on the type of any of the operands 
-    * Type casting is not based on the value of any of the operands+    * Type conversion is not based on the value of any of the operands
   * Operators will throw a ''%%TypeError%%'' for unsupported types   * Operators will throw a ''%%TypeError%%'' for unsupported types
  
-In case an operator can work with several (or all) types, the operands need to match as no casting will be done by those operators.+In case an operator can work with several (or all) types, the operand types need to match as no type conversion will be done by those operators.
  
 The one exception is that [[http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.2|widening primitive conversion]] is allowed for ''%%int%%'' to ''%%float%%''. When doing a operation with an ''%%int%%'' and a ''%%float%%'', the ''%%int%%'' will silently casted to a ''%%float%%''. The one exception is that [[http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.2|widening primitive conversion]] is allowed for ''%%int%%'' to ''%%float%%''. When doing a operation with an ''%%int%%'' and a ''%%float%%'', the ''%%int%%'' will silently casted to a ''%%float%%''.
 +
 +Using ''strict_operators'' never changes the outcome of an operation.
  
 ===== Details for operands ===== ===== Details for operands =====
Line 59: Line 61:
  
 When used with a ''%%bool%%'', ''%%string%%'', ''%%array%%'', ''%%object%%'', or ''%%resource%%'' operand, a ''%%TypeError%%'' will be thrown. When used with a ''%%bool%%'', ''%%string%%'', ''%%array%%'', ''%%object%%'', or ''%%resource%%'' operand, a ''%%TypeError%%'' will be thrown.
 +
 +Custom compare handlers of objects (like ''DateTime'' and ''gmp'') will be applied regardless of ''strict_operators''. The ''ZEND_COMPARE_OBJECTS_FALLBACK'' macro will throw a ''TypeError'' if two objects are compared with different handlers.
  
 ==== String concatenation ==== ==== String concatenation ====
Line 89: Line 93:
  
 There a no changes to the ternary (''%%?:%%'') and null coalescing (''%%??%%'') operator. There a no changes to the ternary (''%%?:%%'') and null coalescing (''%%??%%'') operator.
- 
-===== Switch control structure ===== 
- 
-The strict_operators directive may affect ''%%switch%%''. This is decided through a secondary vote. 
- 
-The ''%%switch%%'' statement will not perform any type conversion. Comparison will be done similar to the identical (''%%===%%'') operator, rather the equal (''%%==%%'') operator. 
- 
-<code php> 
-function match($value) 
-{ 
-  switch ($value) { 
-    case ["foo" => 42, "bar" => 1]: 
-      return "foobar"; 
-      break; 
-    case null: 
-      return "null"; 
-      break; 
-    case 0: 
-      return "zero"; 
-      break; 
-    case "1e1": 
-      return "1e1"; 
-      break; 
-    case "10": 
-      return "10"; 
-      break; 
-    default: 
-      throw new Exception("Unexpected value"); 
-  } 
-} 
- 
-match(["bar" => 1, "foo" => 42]); // "foobar" 
-match(0);                         // "zero" 
-match("10");                      // "10" 
-match("foo");                     // Exception("Unexpected value") 
-</code> 
  
 ===== Motivating examples ===== ===== Motivating examples =====
Line 152: Line 120:
 This can lead to issues when numeric comparison is not expected, for example between two hexidecimal values. The hexidecimal value is instead interpreted as number with scientific notation. This can lead to issues when numeric comparison is not expected, for example between two hexidecimal values. The hexidecimal value is instead interpreted as number with scientific notation.
  
-<code>+<code php>
 $red = '990000'; $red = '990000';
 $purple = '9900e2'; $purple = '9900e2';
Line 185: Line 153:
 $a < $b; // true $a < $b; // true
 </code> </code>
- 
-The logic of relational operators other than ''%%==%%'', ''%%===%%'', ''%%!=%%'' and ''%%!==%%'' has limited practical use. 
  
 ==== Strict vs non-strict comparison of arrays ==== ==== Strict vs non-strict comparison of arrays ====
Line 197: Line 163:
  
 To compare the values of two arrays in a strict way while not concerned about the order, requires ordering the array by key prior to comparison. To compare the values of two arrays in a strict way while not concerned about the order, requires ordering the array by key prior to comparison.
- 
-==== Switch control structure ==== 
- 
-The ''%%switch%%'' statement does a non-strict comparison. This can lead to unexpected results; 
- 
-<code php> 
-function match($value) 
-{ 
-  switch ($value) { 
-    case 2: 
-      return "double"; 
-      break; 
-    case 1: 
-      return "single"; 
-      break; 
-    case 0: 
-      return "none"; 
-      break; 
-    default: 
-      throw new Exception("Unexpected value"); 
-  } 
-} 
- 
-match("foo"); // "none" 
-</code> 
  
 ==== Inconsistent behavior ==== ==== Inconsistent behavior ====
Line 243: Line 184:
  
 This is proposed for PHP 8.0. This is proposed for PHP 8.0.
- 
-===== FAQ ===== 
- 
-[[rfc/strict_operators/faq|See the FAQ of this RFC]] 
  
 ===== Unaffected PHP Functionality ===== ===== Unaffected PHP Functionality =====
Line 254: Line 191:
   * Does not affect any functionality concerning explicit typecasting.   * Does not affect any functionality concerning explicit typecasting.
   * Is largely unaffected by other proposals like [[rfc/string_to_number_comparison|PHP RFC: Saner string to number comparisons]] that focus on improving type juggling at the cost of breaking BC.   * Is largely unaffected by other proposals like [[rfc/string_to_number_comparison|PHP RFC: Saner string to number comparisons]] that focus on improving type juggling at the cost of breaking BC.
 +
 +===== FAQ =====
 +
 +This RFC has an [[rfc/strict_operators/faq|FAQ]] that answers some questions
 +
 +  * [[rfc/strict_operators/faq#what_has_been_changed_since_the_initial_proposal|What has been changed since the initial proposal?]]
 +  * [[rfc/strict_operators/faq#why_use_a_directive_instead_of_applying_this_behavior_as_default|Why use a directive instead of applying this behavior as default?]]
 +  * [[rfc/strict_operators/faq#why_does_and_only_support_int_and_float_operands|Why does == and != only support int and float operands?]]
 +  * [[rfc/strict_operators/faq#why_don_t_comparison_operators_support_strings|Why don't comparison operators support strings?]]
 +  * [[rfc/strict_operators/faq#why_does_the_concatenation_operator_cast_but_arithmetic_operators_don_t|Why does the concatenation operator cast, but arithmetic operators don't?]]
 +  * [[rfc/strict_operators/faq#will_comparing_a_number_to_a_numeric_string_work_with_strict_operators|Will comparing a number to a numeric string work with strict_operators?]]
 +  * [[rfc/strict_operators/faq#how_can_arrays_be_compared_as_unsorted_hashmaps|How can arrays be compared as unsorted hashmaps?]]
 +  * [[rfc/strict_operators/faq#how_can_objects_be_compared_by_property|How can objects be compared by property?]]
 +  * [[rfc/strict_operators/faq#why_isn_t_is_allowed_to_increment_strings_with_strict_operators|Why isn't is allowed to increment strings with strict_operators?]]
 +  * [[rfc/strict_operators/faq#are_built-in_functions_affected_by_strict_operators|Are built-in functions affected by strict_operators?]]
 +  * [[rfc/strict_operators/faq#can_relational_operators_be_allowed_for_arrays|Can relational operators be allowed for arrays?]]
 +  * [[rfc/strict_operators/faq#why_is_switch_not_affected|Why is switch not affected?]]
 +  * [[rfc/strict_operators/faq#are_there_cases_where_a_statement_doesn_t_throw_a_typeerror_but_yields_a_different_result|Are there cases where a statement doesn't throw a TypeError but yields a different result?]]
 +  * [[rfc/strict_operators/faq#will_this_directive_disable_type_juggling_altogether|Will this directive disable type juggling altogether?]]
  
 ===== Implementation ===== ===== Implementation =====
Line 262: Line 218:
  
 Primary vote: Accept the RFC and merge the patch? Yes/No. Requires a 2/3 majority. Primary vote: Accept the RFC and merge the patch? Yes/No. Requires a 2/3 majority.
- 
-Secondary vote: Should strict_operators affect the switch statement? Yes/No Requires a 50%+1 majority. 
  
rfc/strict_operators.1594036143.txt.gz · Last modified: 2020/07/06 11:49 by jasny