rfc:internal_method_return_types

Differences

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

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
rfc:internal_method_return_types [2021/03/22 11:19] kocsismaterfc:internal_method_return_types [2021/05/14 13:57] (current) kocsismate
Line 2: Line 2:
   * Date: 2021-03-06   * Date: 2021-03-06
   * Author: Máté Kocsis <kocsismate@php.net>   * Author: Máté Kocsis <kocsismate@php.net>
-  * Status: Under Discussion+  * Status: Implemented
   * Implementation: https://github.com/php/php-src/pull/6548   * Implementation: https://github.com/php/php-src/pull/6548
 +  * Target Version: PHP 8.1 
  
 ===== Introduction ===== ===== Introduction =====
Line 67: Line 68:
 </code> </code>
  
-Unfortunately, union return types impose a compatibility challenge for libraries: as this construct is only supported since PHP 8.0, libraries would have to accept the fact by default that their code triggers ''E_DEPRECATED'' notices on PHP 8.1 if they also want to support PHP versions below 8.0. As a remedy, this RFC proposes to add a ''SuppressReturnTypeNotice'' attribute which could be used to suppress the related ''E_DEPRECATED'' notices. Thanks to the backward compatible syntax of attributes, this can be done in code which is compatible with PHP 7 and below.+Unfortunately, union return types impose a compatibility challenge for libraries: as this construct is only supported since PHP 8.0, libraries would have to accept the fact by default that their code triggers ''E_DEPRECATED'' notices on PHP 8.1 if they also want to support PHP versions below 8.0. As a remedy, this RFC proposes to add a ''ReturnTypeWillChange'' attribute which could be used to suppress the related ''E_DEPRECATED'' notices. Thanks to the backward compatible syntax of attributes, this can be done in code which is compatible with PHP 7 and below.
  
 <code php> <code php>
Line 75: Line 76:
      * @return DateTime|false      * @return DateTime|false
      */      */
-    #[SuppressReturnTypeNotice]+    #[ReturnTypeWillChange]
     public function modify(string $modifier) { return false; }     public function modify(string $modifier) { return false; }
 } }
Line 82: Line 83:
 </code> </code>
  
-====== Reflection ======+===== Reflection =====
  
 As the tentative return type declarations in question wouldn't be enforced in PHP 8 versions, ''ReflectionMethod::hasReturnType()'' and ''ReflectionMethod::getReturnType()'' won't take these into account until PHP 9.0. As the tentative return type declarations in question wouldn't be enforced in PHP 8 versions, ''ReflectionMethod::hasReturnType()'' and ''ReflectionMethod::getReturnType()'' won't take these into account until PHP 9.0.
  
-===== Backward Incompatible Changes ===== +On the other handtwo new methods are proposed for addition to the ''ReflectionMethod'' class in order to provide reflection information about tentative return types:
- +
-In PHP 8.1an ''E_DEPRECATED'' notice would be raised for each method which has an incompatible return type with its overridden internal method. In PHP 9.0, incompatible return types would always trigger a fatal error. +
- +
-====== Exposing tentative return types to userland ====== +
- +
-The same mechanism can be exposed for userland methods so that libraries can also benefit from it when preparing for adding return type declarations. For this purpose, a ''TentativeReturnType'' attribute is proposed as a secondary vote:+
  
 <code php> <code php>
-class Foo+class ReflectionMethod
 { {
-    #[TentativeReturnType] +    public function hasTentativeReturnType(): bool {} 
-    public function bar(): string +    public function getTentativeReturnType(): ?ReflectionType {}
-    { +
-        return "bar"; +
-    }+
 } }
- 
-class Foo2 extends Foo 
-{ 
-    public function bar() 
-    { 
-    } 
-} 
- 
-class Foo3 extends Foo 
-{ 
-    #[SuppressReturnTypeNotice] 
-    public function bar(): string|false 
-    { 
-        return []; 
-    } 
-} 
- 
-$foo2 = new Foo2(); 
-$foo2->bar(); 
- 
-$foo3 = new Foo3(); 
-$foo3->bar(); 
- 
-// Deprecated: Declaration of Foo2::bar() should be compatible with Foo::bar(): string 
-// Fatal error: Uncaught TypeError: Foo3::bar(): Return value must be of type string|false, array returned 
 </code> </code>
  
-By attaching the ''TentativeReturnType'' attribute to ''Foo::bar()'', the native return type declaration becomes tentative, and only the previously introduced ''E_DEPRECATED'' notice is emited. While ''Foo3::bar()'' suppresses this notice, ''TypeError'' is thrown when this method is invoked because its own return type is enforced as usual, and any child methods will respect it as well.+===== Backward Incompatible Changes =====
  
-It should also be highlighted that ''TentativeReturnType'' and ''SuppressReturnType'' is only effective for immediate children:+In PHP 8.1, an ''E_DEPRECATED'' notice would be raised for each method which has an incompatible return type with its overridden internal method. In PHP 9.0, incompatible return types would always trigger a fatal error.
  
-<code php> +===== Vote =====
-class Foo +
-+
-    #[TentativeReturnType] +
-    public function bar(): string +
-    { +
-        return "bar"; +
-    } +
-}+
  
-class Foo2 extends Foo +Voting started 2021-04-22 and ends 2021-05-06 UTC. The vote requires 2/3 majority to be accepted.
-+
-    #[SuppressReturnTypeNotice] +
-    public function bar(): array +
-    { +
-        return []; +
-    } +
-}+
  
-class Foo3 extends Foo2 +<doodle title="Add return type declarations for internal methods in the proposed schedule?" auth="kocsismate" voteType="single" closed="true"
-+   * Yes 
-    public function bar(): string +   * No 
-    { +</doodle>
-        return "bar"; +
-    } +
-+
- +
-// Fatal error: Declaration of Foo3::bar(): string must be compatible with Foo2::bar(): array +
-</code> +
- +
-This behaviour is necessary to keep backward compatibility, so that ''Foo3::bar()'' can't override the return type declaration of ''Foo2::bar()'' with types that clients are not prepared for+
- +
-In addition to the ''TentativeReturnType'' attribute, two new methods are proposed for addition to the ''ReflectionMethod'' class in order to provide reflection information about tentative return types: +
- +
-<code php+
-class ReflectionMethod +
-+
-    public function hasTentativeReturnType(): bool {} +
-    public function getTentativeReturnType(): ?ReflectionType {} +
-} +
-</code> +
- +
-===== Vote =====+
  
-Primary vote: Add return type declarations tentatively for internal methods? The vote requires 2/3 majority to be accepted. 
  
-Secondary vote: Add the ''TentativeReturnType'' attribute? The vote requires 2/3 majority to be accepted. 
rfc/internal_method_return_types.1616411997.txt.gz · Last modified: 2021/03/22 11:19 by kocsismate