]> granicus.if.org Git - php/commitdiff
Fixed bug #80190
authorNikita Popov <nikita.ppv@gmail.com>
Tue, 6 Oct 2020 08:20:27 +0000 (10:20 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Tue, 6 Oct 2020 08:20:27 +0000 (10:20 +0200)
NEWS
ext/reflection/php_reflection.c
ext/reflection/tests/bug80190.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 00f463c4915d0f045b1d52a736e2a4de3c96db0c..64a2b0fa7a782d8fae85aaa5b891a810c1c86f7a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,10 @@ PHP                                                                        NEWS
   . Fixed bug #80184 (Complex expression in while / if statements resolves to
     false incorrectly). (Nikita)
 
+- Reflection:
+  . Fixed bug #80190 (ReflectionMethod::getReturnType() does not handle static
+    as part of union type). (Nikita)
+
 - SPL:
   . Fixed bug #65387 (Circular references in SPL iterators are not garbage
     collected). (Nikita)
index 7b9c37d1eb51e2547a945eb150b959070c5236e0..0bc4509d5ee5aa845217e334ba723951354c28cd 100644 (file)
@@ -2952,6 +2952,9 @@ ZEND_METHOD(ReflectionUnionType, getTypes)
 
        type_mask = ZEND_TYPE_PURE_MASK(param->type);
        ZEND_ASSERT(!(type_mask & MAY_BE_VOID));
+       if (type_mask & MAY_BE_STATIC) {
+               append_type_mask(return_value, MAY_BE_STATIC);
+       }
        if (type_mask & MAY_BE_CALLABLE) {
                append_type_mask(return_value, MAY_BE_CALLABLE);
        }
diff --git a/ext/reflection/tests/bug80190.phpt b/ext/reflection/tests/bug80190.phpt
new file mode 100644 (file)
index 0000000..16f2fbb
--- /dev/null
@@ -0,0 +1,67 @@
+--TEST--
+Bug #80190: ReflectionMethod::getReturnType() does not handle static as part of union type
+--FILE--
+<?php
+
+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) . "($type)";
+        }
+        
+        print join(', ', $types) . PHP_EOL;
+    }
+
+    print PHP_EOL;
+}
+
+?>
+--EXPECT--
+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(stdClass), ReflectionNamedType(self)
+
+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 2 element(s)
+    type(s) in union: ReflectionNamedType(stdClass), ReflectionNamedType(static)