rfc:returntypehinting
Differences
This shows you the differences between two versions of the page.
rfc:returntypehinting [2014/11/07 01:15] – Close vote because of outstanding issue. levim | rfc:returntypehinting [2017/09/22 13:28] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | + | This RFC has moved to [[https://wiki.php.net/rfc/return_types]]. | |
- | ====== PHP RFC: Return Type Declarations ====== | + | |
- | * Version: 1.3.1 | + | |
- | * Date: 2014-03-20 | + | |
- | * Author: Levi Morrison < | + | |
- | * Status: Voting | + | |
- | * First Published at: https:// | + | |
- | + | ||
- | ===== Introduction ===== | + | |
- | Many developers would like to be able to declare the return type of a function. The basic idea of declaring a return type has been included in at least three RFCs and has been discussed in a few other places (see [[# | + | |
- | + | ||
- | Declaring return types has several motivators and use-cases: | + | |
- | * Providing return types on interface implementations((See [[# | + | |
- | * Preventing sub-classes | + | |
- | * Preventing unintended return types | + | |
- | * Documenting return type information that is not easily invalidated (unlike comments). | + | |
- | + | ||
- | ===== Proposal ===== | + | |
- | This proposal adds an optional return type declaration to function declarations including closures, functions, generators, interface method declarations and class declarations. This RFC does not change the existing type declarations nor does it add new ones (see [[# | + | |
- | + | ||
- | Example of '' | + | |
- | + | ||
- | " | + | |
- | inner_statement_list | + | |
- | " | + | |
- | + | ||
- | Here is a brief example of the syntax in action: | + | |
- | < | + | |
- | function foo(): array { | + | |
- | return []; | + | |
- | } | + | |
- | </ | + | |
- | More examples can be found in the [[# | + | |
- | + | ||
- | //Code which does not declare a return type | + | |
- | | + | |
- | + | ||
- | ==== Variance and Signature Validation ==== | + | |
- | The enforcement of the declared return type during inheritance is covariant; this allows an over-riding method to declare a return type that is a sub-type of the original (illustrated in [[# | + | |
- | + | ||
- | If a mismatch is detected during compile time (e.g. a class improperly overriding a return type) then '' | + | |
- | + | ||
- | Covariant return types are considered to be type sound and are used in many other languages((C++, | + | |
- | + | ||
- | ==== Position of Type Declaration ==== | + | |
- | The two major conventions in other programming languages for placing return type information are: | + | |
- | + | ||
- | * Before the function name | + | |
- | * After the parameter list's closing parenthesis | + | |
- | + | ||
- | The former position has been proposed in the past and the RFCs were either declined or withdrawn. One cited issue is that many developers wanted to preserve the ability to search for < | + | |
- | + | ||
- | The latter position is used in several languages(([[http:// | + | |
- | + | ||
- | Declaring the return type after the parameter list had no shift/ | + | |
- | + | ||
- | ==== Returning by Reference ==== | + | |
- | + | ||
- | This RFC does not change the location of ''&'' | + | |
- | < | + | |
- | function & | + | |
- | return $data; | + | |
- | } | + | |
- | + | ||
- | function & | + | |
- | return $data; | + | |
- | } | + | |
- | </ | + | |
- | + | ||
- | ==== Disallowing NULL on Return Types ==== | + | |
- | Consider the following function: | + | |
- | + | ||
- | < | + | |
- | function foo(): DateTime { | + | |
- | return null; // invalid | + | |
- | } | + | |
- | </ | + | |
- | + | ||
- | It declares that it will return '' | + | |
- | + | ||
- | - This aligns with current parameter type behavior. When parameters have a type declared, a value of '' | + | |
- | - Allowing '' | + | |
- | + | ||
- | The [[rfc: | + | |
- | + | ||
- | ==== Methods which cannot declare return types ==== | + | |
- | + | ||
- | Class constructors, | + | |
- | + | ||
- | * ''< | + | |
- | * ''< | + | |
- | * ''< | + | |
- | + | ||
- | ==== Examples ==== | + | |
- | Here are some snippets of both valid and invalid usage. | + | |
- | + | ||
- | === Examples of Valid Use === | + | |
- | < | + | |
- | // Covariant return-type: | + | |
- | + | ||
- | interface Collection { | + | |
- | function map(callable $fn): Collection; | + | |
- | } | + | |
- | + | ||
- | interface Set extends Collection { | + | |
- | function map(callable $fn): Set; | + | |
- | } | + | |
- | </ | + | |
- | < | + | |
- | // Overriding a method that did not have a return type: | + | |
- | interface Comment {} | + | |
- | interface CommentsIterator extends Iterator { | + | |
- | function current(): Comment; | + | |
- | } | + | |
- | </ | + | |
- | < | + | |
- | // Using a generator: | + | |
- | + | ||
- | interface Collection extends IteratorAggregate { | + | |
- | function getIterator(): | + | |
- | } | + | |
- | + | ||
- | class SomeCollection implements Collection { | + | |
- | function getIterator(): | + | |
- | foreach ($this-> | + | |
- | yield $key => $value; | + | |
- | } | + | |
- | } | + | |
- | } | + | |
- | </ | + | |
- | + | ||
- | === Examples of Invalid Use === | + | |
- | + | ||
- | The error messages are taken from the current patch. | + | |
- | + | ||
- | ---- | + | |
- | < | + | |
- | // Returned type does not match the type declaration | + | |
- | + | ||
- | function get_config(): | + | |
- | return 42; | + | |
- | } | + | |
- | get_config(); | + | |
- | </ | + | |
- | '' | + | |
- | + | ||
- | ---- | + | |
- | + | ||
- | < | + | |
- | // Int is not a valid type declaration | + | |
- | + | ||
- | function answer(): int { | + | |
- | return 42; | + | |
- | } | + | |
- | answer(); | + | |
- | </ | + | |
- | '' | + | |
- | + | ||
- | ---- | + | |
- | + | ||
- | < | + | |
- | // Cannot return null with a return type declaration | + | |
- | + | ||
- | function foo(): DateTime { | + | |
- | return null; | + | |
- | } | + | |
- | foo(); | + | |
- | </ | + | |
- | '' | + | |
- | + | ||
- | ---- | + | |
- | + | ||
- | < | + | |
- | // Missing return type on override | + | |
- | + | ||
- | class User {} | + | |
- | + | ||
- | interface UserGateway { | + | |
- | function find($id): User; | + | |
- | } | + | |
- | + | ||
- | class UserGateway_MySql implements UserGateway { | + | |
- | // must return User or subtype of User | + | |
- | function find($id) { | + | |
- | return new User(); | + | |
- | } | + | |
- | } | + | |
- | </ | + | |
- | '' | + | |
- | + | ||
- | ---- | + | |
- | + | ||
- | < | + | |
- | // Generator return types can only be declared as Generator, Iterator or Traversable (compile time check) | + | |
- | + | ||
- | function foo(): array { | + | |
- | yield []; | + | |
- | } | + | |
- | </ | + | |
- | '' | + | |
- | + | ||
- | + | ||
- | ==== Multiple Return Types ==== | + | |
- | This proposal specifically does not allow declaring multiple return types; this is out of the scope of this RFC and would require a separate RFC if desired. | + | |
- | + | ||
- | If you want to use multiple return types, simply omit a return type declaration and rely on PHP's excellent dynamic nature. | + | |
- | + | ||
- | ==== Reflection ==== | + | |
- | + | ||
- | A new '' | + | |
- | + | ||
- | The following two methods have been added to '' | + | |
- | + | ||
- | - '' | + | |
- | - '' | + | |
- | + | ||
- | Note that '' | + | |
- | + | ||
- | === ReflectionType === | + | |
- | < | + | |
- | class ReflectionType implements Reflector { | + | |
- | const TYPE_UNDECLARED = 0; | + | |
- | const TYPE_ARRAY; | + | |
- | const TYPE_CALLABLE; | + | |
- | const TYPE_OBJECT; | + | |
- | + | ||
- | public function getTypeConstant(); | + | |
- | public function getName(); /* returns the string version of the type */ | + | |
- | public function __toString(); | + | |
- | } | + | |
- | </ | + | |
- | + | ||
- | + | ||
- | This API was designed so you could use '' | + | |
- | + | ||
- | < | + | |
- | // If ReflectionType mirrored ReflectionParameter' | + | |
- | $ReflectionType = /* ... */; | + | |
- | + | ||
- | if ($ReflectionType !== false) { | + | |
- | if ($ReflectionType-> | + | |
- | // ... | + | |
- | } elseif ($ReflectionType-> | + | |
- | // ... | + | |
- | } elseif ($ReflectionType-> | + | |
- | // ... | + | |
- | } else { | + | |
- | // handle unknown type (future compatibility) | + | |
- | } | + | |
- | } else { | + | |
- | // ... | + | |
- | } | + | |
- | </ | + | |
- | < | + | |
- | // The proposed API: | + | |
- | $ReflectionType = /* ... */; | + | |
- | + | ||
- | switch ($ReflectionType-> | + | |
- | case ReflectionType:: | + | |
- | // ... | + | |
- | break; | + | |
- | case ReflectionType:: | + | |
- | // ... | + | |
- | break; | + | |
- | case ReflectionType:: | + | |
- | // ... | + | |
- | break; | + | |
- | case ReflectionType:: | + | |
- | // ... | + | |
- | break; | + | |
- | default: | + | |
- | // handle unknown type (future compatibility) | + | |
- | break; | + | |
- | } | + | |
- | </ | + | |
- | + | ||
- | Additionally, | + | |
- | + | ||
- | < | + | |
- | $ReflectionType = /* ... */; | + | |
- | + | ||
- | if (!$ReflectionType-> | + | |
- | // no type provided | + | |
- | } | + | |
- | </ | + | |
- | + | ||
- | Compared to the proposed API: | + | |
- | < | + | |
- | $ReflectionType = /* ... */; | + | |
- | + | ||
- | if ($ReflectionType-> | + | |
- | // no type provided | + | |
- | } | + | |
- | </ | + | |
- | + | ||
- | Note that this RFC does not alter '' | + | |
- | + | ||
- | ==== Differences from Past RFCs ==== | + | |
- | This proposal differs from past RFCs in several key ways: | + | |
- | + | ||
- | * **The return type is positioned after the parameter list.** See [[# | + | |
- | * **We keep the current type options.** Past proposals have suggested new types such as '' | + | |
- | * **We keep the current search patterns.** You can still search for < | + | |
- | * **We allow return type declarations on all function types**. Will Fitch' | + | |
- | * **We do not modify or add keywords.** Past RFCs have proposed new keywords such as '' | + | |
- | + | ||
- | ===== Other Impact ===== | + | |
- | + | ||
- | ==== On Backward Compatiblity ==== | + | |
- | This RFC is backwards compatible with previous PHP releases. | + | |
- | + | ||
- | ==== On SAPIs ==== | + | |
- | There is no impact on any SAPI. | + | |
- | + | ||
- | ==== On Existing Extensions ===== | + | |
- | The structs '' | + | |
- | + | ||
- | ==== On Performance ==== | + | |
- | An informal test indicates that performance has not seriously degraded. More formal performance testing can be done before voting phase. | + | |
- | + | ||
- | ===== Proposed PHP Version(s) ===== | + | |
- | This RFC targets PHP 7. | + | |
- | + | ||
- | ===== Vote ===== | + | |
- | This RFC modifies the PHP language syntax and therefore requires a two-third majority of votes. | + | |
- | + | ||
- | < | + | |
- | A bug was found during the voting period that will require enough changes to how the RFC works that voting has been cancelled. | + | |
- | <doodle title=" | + | |
- | * Yes | + | |
- | * No | + | |
- | </ | + | |
- | + | ||
- | ===== Patches and Tests ===== | + | |
- | + | ||
- | Levi Morrison has provided a [[https:// | + | |
- | + | ||
- | Joe Watkins provided [[https:// | + | |
- | + | ||
- | ===== Future Work ===== | + | |
- | Ideas for future work which are out of the scope of this RFC include: | + | |
- | + | ||
- | * Allowing functions to declare that they do not return anything at all ('' | + | |
- | * Allowing nullable types(such as < | + | |
- | * Unifying the reflection type API by having '' | + | |
- | * Improving parameter variance. Currently parameter types are invariant while they could be contravariant. | + | |
- | * Improving runtime performance by doing type analysis. | + | |
- | * Updating documentation to use the new return type syntax. | + | |
- | + | ||
- | ===== References ===== | + | |
- | * [[rfc: | + | |
- | * [[rfc: | + | |
- | * [[rfc: | + | |
- | * [[http:// | + | |
- | + | ||
- | In the meeting in Paris on November 2005 it was decided that PHP should have return type declarations and some suggestions were made for syntax. Suggestion 5 is nearly compatible with this RFC; however, it requires the addition of a new token '' | + | |
- | + | ||
- | The following (tiny) patch would allow the syntax in suggestion 5 to be used alongside the current syntax. This RFC does not propose that both versions of syntax should be used; the patch just shows how similar this RFC is to that suggestion from 2005. | + | |
- | + | ||
- | https:// | + | |
- | + | ||
- | ===== Changelog ===== | + | |
- | + | ||
- | * v1.1: RFC now targets PHP 7. | + | |
- | * v1.2: disallow return types for constructors, | + | |
- | * v1.3: reworked Reflection support to use new ReflectionType class | + | |
- | * v1.3.1: renamed '' | + |
rfc/returntypehinting.1415322903.txt.gz · Last modified: 2017/09/22 13:28 (external edit)