rfc:non_nullable_property_checks

Differences

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

Link to this comparison view

Both sides previous revisionPrevious revision
rfc:non_nullable_property_checks [2019/01/24 18:54] – getting somewhere; not ready for discussion yet, though, I think imsoprfc:non_nullable_property_checks [2019/01/24 22:15] (current) imsop
Line 19: Line 19:
   * a simpler contract, that the property *can only be set to* the given type   * a simpler contract, that the property *can only be set to* the given type
  
-When a property has a static default value, or allows nulls, the distinction rarely matters: in normal use, the property starts life with a valid value, and can only be set to a valid value; therefore, it will always have a valid value. However, if null is not a valid value, and there is no static default, the property must start in an invalid state, and it is easy to write code which leaves it in that state.+When a property has a static default value, or allows nulls, the distinction rarely matters: in normal use, the property starts life with a valid value, and can only be set to a valid value. However, if null is not a valid value, and there is no static default, the property must start in an invalid state, and it is easy to write code which leaves it in that state.
  
 The stronger contract requires extremely careful language design, as there must be some defined point in the program where the asserted state first becomes true; for instance, in [[https://docs.swift.org/swift-book/LanguageGuide/Initialization.html|Swift's two-phase initialization]], all introduced properties must be in a valid state before the parent initializer is called. This is difficult if not impossible to add to an existing, highly-dynamic, language such as PHP. The stronger contract requires extremely careful language design, as there must be some defined point in the program where the asserted state first becomes true; for instance, in [[https://docs.swift.org/swift-book/LanguageGuide/Initialization.html|Swift's two-phase initialization]], all introduced properties must be in a valid state before the parent initializer is called. This is difficult if not impossible to add to an existing, highly-dynamic, language such as PHP.
Line 38: Line 38:
                 case 'development':                 case 'development':
                     $this->mode = 'dev';                     $this->mode = 'dev';
 +### The bug is actually here
                 break;                 break;
                 case 'prod':                 case 'prod':
Line 55: Line 56:
         public function __construct() {         public function __construct() {
             $this->util = new \VendorOne\LowLevelLib\ImplementationDetail('dev');             $this->util = new \VendorOne\LowLevelLib\ImplementationDetail('dev');
-            # Proposed TypeError: "Typed property $value must be initialized before end of constructor ... in ImplementationDetail::__construct()"+### Proposed TypeError: "Typed property $value must be initialized before end of constructor ... in ImplementationDetail::__construct()"
         }         }
                  
Line 68: Line 69:
          
     echo $tool->getScore();     echo $tool->getScore();
-    # Current TypeError: "Typed property $value must not be accessed before initialization ... in UsefulTool->getScore()"+### Current TypeError: "Typed property $value must not be accessed before initialization ... in UsefulTool->getScore()"
 } }
 </code> </code>
Line 86: Line 87:
  
   * Immediately after an object is constructed (to catch errors in ''%%__construct%%'')   * Immediately after an object is constructed (to catch errors in ''%%__construct%%'')
-  * Immediately after an object is deserialized (to catch errors in ''%%__sleep%%'' / ''Unserialize'' / [[https://wiki.php.net/rfc/custom_object_serialization|__unserialize]])+  * Immediately after an object is unserialized (to catch errors in ''%%__sleep%%'' / ''Unserialize'' / [[https://wiki.php.net/rfc/custom_object_serialization|__unserialize]])
  
 ===== Backward Incompatible Changes ===== ===== Backward Incompatible Changes =====
Line 93: Line 94:
 If it is for some reason delayed, there is the possibility that code which runs under PHP 7.4 will start raising errors due to the new checks. If it is for some reason delayed, there is the possibility that code which runs under PHP 7.4 will start raising errors due to the new checks.
  
-===== Proposed PHP Version(s) ===== +===== Performance =====
-PHP 7.4+
  
-===== RFC Impact =====+Although the checks will obviously have some overhead, this is expected to be close to zero for classes with no typed properties (since we can check using ''ZEND_CLASS_HAS_TYPE_HINTS''), and equivalent to one additional access on each property for classes with them.
  
-==== To Existing Extensions ==== 
-Will existing extensions be affected? 
  
-==== To Opcache ==== +===== Proposed PHP Version ===== 
-It is necessary to develop RFC's with opcache in mind, since opcache is a core extension distributed with PHP. +PHP 7.4
- +
-Please explain how you have verified your RFC's compatibility with opcache.+
  
 ===== Open Issues ===== ===== Open Issues =====
-Make sure there are no open issues when the vote starts!+ 
 +  * Are there other places that this assertion can be added? 
 +  * Should we expose ''zend_check_properties_initialized'' to userland, so that users can manually assert that an object is fully initialized after creating or manipulating in a way not handled by the automatic checks?
  
 ===== Unaffected PHP Functionality ===== ===== Unaffected PHP Functionality =====
-List existing areas/features of PHP that will not be changed by the RFC. 
  
-This helps avoid any ambiguity, shows that you have thought deeply about the RFC's impactand helps reduces mail list noise.+It is important to understand that this proposal does not guarantee that a typed property will always have a valid value. Among others, the following may still lead to uninitialized properties: 
 + 
 +  * Calling ''unset()'' on a non-nullable property. Although normally undesirablethis is used in conjunction with ''__get'' for some exotic use cases. 
 +  * Creating an object with ''ReflectionClass::newWithoutConstructor''.
  
-===== Future Scope ===== 
-This section details areas where the feature might be improved in future, but that are not currently proposed in this RFC. 
  
 ===== Proposed Voting Choices ===== ===== Proposed Voting Choices =====
-Include these so readers know where you are heading and can discuss the proposed voting options.+**Should checks be added to detect objects which are not fully initialized after common cases such as construction.**
  
-State whether this project requires a 2/3 or 50%+1 majority (see [[voting]])+This is a change to the behaviour of the language, so requires a 2/3 majority.
  
 ===== Implementation ===== ===== Implementation =====
-TODO+None yet.
  
 ===== References ===== ===== References =====
Line 131: Line 129:
  
 ===== Rejected Features ===== ===== Rejected Features =====
-Keep this updated with features that were discussed on the mail lists.+TODO
rfc/non_nullable_property_checks.1548356040.txt.gz · Last modified: 2019/01/24 18:54 by imsop