rfc:returntypehint2
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
rfc:returntypehint2 [2011/12/17 04:03] – [Introduction] fitchwh | rfc:returntypehint2 [2017/09/22 13:28] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
Line 3: | Line 3: | ||
* Date: 2011-12-13 | * Date: 2011-12-13 | ||
* Author: Will Fitch < | * Author: Will Fitch < | ||
- | * Status: | + | * Status: |
===== Introduction ===== | ===== Introduction ===== | ||
- | The purpose behind this RFC is to introduce return type hinting to PHP class methods. | + | The purpose behind this RFC is to introduce return type hinting to PHP class methods. |
- | ==== Syntactical | + | ==== Syntactical |
=== Approach === | === Approach === | ||
Line 20: | Line 20: | ||
</ | </ | ||
- | When writing this patch, I saw no reason diverge from this direction. | + | When writing this patch, I saw no reason diverge from this direction. |
=== Using Existing PHP Standards === | === Using Existing PHP Standards === | ||
- | With the introduction to the new object model in PHP 5 came parameter type hinting. | + | With the introduction to the new object model in PHP 5 came parameter type hinting. |
- | + | ||
+ | This implementation of return type hinting follows the same approach. | ||
+ | === Returning NULL === | ||
+ | By default, if you specify a return type hint, you **must** return that type. However, a new keyword " | ||
+ | === Example Implementations === | ||
+ | <code php> | ||
+ | <?php | ||
+ | class MyClass | ||
+ | { | ||
+ | public ArrayIterator getIterator() | ||
+ | { | ||
+ | return new ArrayIterator(); | ||
+ | } | ||
+ | | ||
+ | public array getArray() | ||
+ | { | ||
+ | $array = array(' | ||
+ | return $array; | ||
+ | } | ||
+ | | ||
+ | public function getMixedValue() | ||
+ | { | ||
+ | return ' | ||
+ | } | ||
+ | | ||
+ | public \ArrayIterator getNamespacedVersion() | ||
+ | { | ||
+ | return new ArrayIterator(); | ||
+ | } | ||
+ | | ||
+ | public callable getCallableString() | ||
+ | { | ||
+ | return ' | ||
+ | } | ||
+ | | ||
+ | // The nullable keyword allows you to return null | ||
+ | protected nullable ArrayObject getArrayObject() | ||
+ | { | ||
+ | return null; | ||
+ | } | ||
+ | | ||
+ | private callable methodModsDontMatter() | ||
+ | { | ||
+ | return ' | ||
+ | } | ||
+ | | ||
+ | ArrayObject methodsDontNeedModsActually() | ||
+ | { | ||
+ | return new ArrayObject(); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | The above examples show how some of the functionality works. | ||
+ | === Interfaces === | ||
+ | The interface changes introduced in this patch provide compile-time validation on inheritance and implementation. | ||
+ | Interface names may also be declared as the type hint for return values. | ||
+ | <code php> | ||
+ | <?php | ||
+ | interface IteratorInterface | ||
+ | { | ||
+ | public ArrayIterator getIterator(); | ||
+ | } | ||
+ | class Users implements IteratorInterface | ||
+ | { | ||
+ | public ArrayIterator getIterator() | ||
+ | { | ||
+ | /* do some work */ | ||
+ | return new ArrayIterator(); | ||
+ | } | ||
+ | } | ||
+ | class Vehicles implements IteratorInterface | ||
+ | { | ||
+ | public ArrayIterator getIterator() | ||
+ | { | ||
+ | /* do some work */ | ||
+ | return new ArrayIterator(); | ||
+ | } | ||
+ | } | ||
- | ==== Why do we need type hinting for methods? ==== | + | class MyClass |
+ | { | ||
+ | public IteratorInterface getTheIterator() | ||
+ | { | ||
+ | return new Vehicles(); // This is valid | ||
+ | } | ||
+ | |||
+ | public IteratorInterface getTheOtherIterator() | ||
+ | { | ||
+ | return new Users(); // This is valid, too | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | The above example shows two classes (Vehicles and Users) that implement an interface (IteratorInterface) and a class that provides methods defining the interface as the return type hint. Any class that implements an interface may be returned from a method that defines such. | ||
+ | === Reflection === | ||
- | ===== Common Misconceptions ===== | + | Reflection has a minor change in this patch. |
+ | ==== Functional Implementation ==== | ||
+ | I will briefly describe the functional changes made, and let the patch do the rest. | ||
- | ===== Proposal and Patch ===== | + | === Parser |
+ | The language parser " | ||
- | ===== Changelog ===== | + | I separated the " |
+ | Second, and not a technical decision, I didn't want to introduce these changes on the first iteration. | ||
+ | |||
+ | === Compiler === | ||
+ | |||
+ | As previously stated, a new function " | ||
+ | |||
+ | I also modified zend_do_begin_function_declaration to declare the type hint as IS_UNUSED and nullify the class name. | ||
+ | |||
+ | I decided to add the type hint data elements to the zend_op_array structure rather than the zend_function union. | ||
+ | |||
+ | === Executor === | ||
+ | |||
+ | Three functions were added to zend_execute.c: | ||
+ | |||
+ | - zend_verify_method_return_type - this verifies if a method adheres to the defined return type | ||
+ | - zend_verify_method_return_error - like its parameter counterpart, | ||
+ | - zend_verify_method_return_class_kind - if it is determined an object is being returned, this function is called to resolve whether a class or interface name should be provided along with the correct error matching that. | ||
+ | |||
+ | The zend_vm_execute.h was modified in multiple places to reference zend_verify_method_return_type. | ||
+ | |||
+ | === Tests === | ||
+ | |||
+ | A total of 21 tests were added to tests/ | ||
+ | |||
+ | * Determine that non-namespaced and namespaced class name don't produce a syntax error | ||
+ | * Determines if a catchable fatal error is raised when an array or object is defined and the following are returned: resource, object, string, integer or double. | ||
+ | * Determine if an E_COMPILE_ERROR is raised when a class implements an interface that defines a method which returns both an array and object, but fails to correctly redefine. | ||
+ | * Determines if a callable works | ||
+ | * Determines if a callable is defined but not returned | ||
+ | |||
+ | |||
+ | ===== Patch ===== | ||
+ | |||
+ | The patch for this is now outdated and gone. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== Changelog ===== | ||
+ | - Updated to include " | ||
+ | - Updated to remove allowing NULL to be returned unconditionally when declaring return types | ||
+ | - Added a new patch which includes a " | ||
+ | - Updated the RFC to take " | ||
rfc/returntypehint2.txt · Last modified: 2017/09/22 13:28 by 127.0.0.1