rfc:returntypehint2
no way to compare when less than two revisions
Differences
This shows you the differences between two versions of the page.
Previous revisionNext revision | |||
— | rfc:returntypehint2 [2012/12/18 22:04] – [Patch] willfitch | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Request for Comments: Method Return Type Hints ====== | ||
+ | * Version: 1.0 | ||
+ | * Date: 2011-12-13 | ||
+ | * Author: Will Fitch < | ||
+ | * Status: Under Discussion | ||
+ | |||
+ | |||
+ | ===== Introduction ===== | ||
+ | |||
+ | The purpose behind this RFC is to introduce return type hinting to PHP class methods. | ||
+ | |||
+ | ==== Syntactical Implementation ==== | ||
+ | |||
+ | === Approach === | ||
+ | |||
+ | Languages like C# and Java provide an elegant syntactical approach to defining this: | ||
+ | |||
+ | < | ||
+ | [method_attributes] [return_type] [method_name] ' | ||
+ | </ | ||
+ | |||
+ | When writing this patch, I saw no reason diverge from this direction. | ||
+ | |||
+ | === Using Existing PHP Standards === | ||
+ | |||
+ | 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(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | 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 === | ||
+ | |||
+ | 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. | ||
+ | |||
+ | === Parser === | ||
+ | |||
+ | The language parser " | ||
+ | |||
+ | 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