php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #80190 ReflectionMethod::getReturnType() does not handle static as part of union type
Submitted: 2020-10-06 06:11 UTC Modified: 2020-10-06 06:46 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: sebastian@php.net Assigned:
Status: Closed Package: Reflection related
PHP Version: 8.0Git-2020-10-06 (Git) OS: Irrelevant
Private report: No CVE-ID: None
 [2020-10-06 06:11 UTC] sebastian@php.net
Description:
------------
Consider this class:

class C
{
    public function m(): stdClass|static
    {
    }
}

ReflectionMethod::getReturnType() returns for C::m() a ReflectionUnionType that contains only a ReflectionNamedType object for "stdClass" but no information about "static".

This blocks PHPUnit's support for test doubles of objects with methods that declare a return type with a union that includes "static" (https://github.com/sebastianbergmann/phpunit/issues/4480, https://github.com/sebastianbergmann/type/issues/14).

Test script:
---------------
<?php declare(strict_types=1);
class C
{
    public function a(): self
    {
    }

    public function b(): stdClass|self
    {
    }

    public function c(): static
    {
    }

    public function d(): stdClass|static
    {
    }
}

foreach ((new ReflectionClass(C::class))->getMethods() as $method) {
    print $method->getDeclaringClass()->getName() . '::' . $method->getName() . '()' . PHP_EOL;
    print '    $method->getReturnType() returns ' . get_class($method->getReturnType()) . PHP_EOL;
    print '    $method->getReturnType()->__toString() returns ' . $method->getReturnType() . PHP_EOL;

    if ($method->getReturnType() instanceof ReflectionUnionType) {
        print '    $method->getReturnType()->getTypes() returns an array with ' . count($method->getReturnType()->getTypes()) . ' element(s)' . PHP_EOL;

        print '    type(s) in union: ';
        
        $types = [];

        foreach ($method->getReturnType()->getTypes() as $type) {
            $types[] = get_class($type);
        }
        
        print join(', ', $types) . PHP_EOL;
    }

    print PHP_EOL;
}


Expected result:
----------------
C::a()
    $method->getReturnType() returns ReflectionNamedType
    $method->getReturnType()->__toString() returns self

C::b()
    $method->getReturnType() returns ReflectionUnionType
    $method->getReturnType()->__toString() returns stdClass|self
    $method->getReturnType()->getTypes() returns an array with 2 element(s)
    type(s) in union: ReflectionNamedType, ReflectionNamedType

C::c()
    $method->getReturnType() returns ReflectionNamedType
    $method->getReturnType()->__toString() returns static

C::d()
    $method->getReturnType() returns ReflectionUnionType
    $method->getReturnType()->__toString() returns stdClass|static
    $method->getReturnType()->getTypes() returns an array with 1 element(s)
    type(s) in union: ReflectionNamedType, SOMETHING FOR STATIC


Actual result:
--------------
C::a()
    $method->getReturnType() returns ReflectionNamedType
    $method->getReturnType()->__toString() returns self

C::b()
    $method->getReturnType() returns ReflectionUnionType
    $method->getReturnType()->__toString() returns stdClass|self
    $method->getReturnType()->getTypes() returns an array with 2 element(s)
    type(s) in union: ReflectionNamedType, ReflectionNamedType

C::c()
    $method->getReturnType() returns ReflectionNamedType
    $method->getReturnType()->__toString() returns static

C::d()
    $method->getReturnType() returns ReflectionUnionType
    $method->getReturnType()->__toString() returns stdClass|static
    $method->getReturnType()->getTypes() returns an array with 1 element(s)
    type(s) in union: ReflectionNamedType


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-10-06 06:46 UTC] sebastian@php.net
Unfortunately, our arcane issue tracker does not let me edit my original report. If if did, I would make the following edits:

* Change "$method->getReturnType()->getTypes() returns an array with 1 element(s)" to "$method->getReturnType()->getTypes() returns an array with 2 element(s)" for C::d() in the "Expected result" section

* Change "ReflectionNamedType, SOMETHING FOR STATIC" to "ReflectionNamedType, ReflectionNamedType" for C::d() in the "Expected result" section

I think it only makes sense to represent "static" the same way "self" is represented.
 [2020-10-06 08:21 UTC] nikic@php.net
Automatic comment on behalf of nikita.ppv@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=dee802498e25e22afb35e550dea1f7b3a8aa0129
Log: Fixed bug #80190
 [2020-10-06 08:21 UTC] nikic@php.net
-Status: Open +Status: Closed
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 16:01:28 2024 UTC