Skip to content

Fix ReflectionGetAttributesMethodReturnTypeExtension for union types#5464

Closed
janedbal wants to merge 1 commit intophpstan:2.1.xfrom
janedbal:fix-reflection-getattributes-union-type
Closed

Fix ReflectionGetAttributesMethodReturnTypeExtension for union types#5464
janedbal wants to merge 1 commit intophpstan:2.1.xfrom
janedbal:fix-reflection-getattributes-union-type

Conversation

@janedbal
Copy link
Copy Markdown
Contributor

Bug

When calling getAttributes() on a union type like ReflectionClass|ReflectionProperty, the ReflectionGetAttributesMethodReturnTypeExtension fails to fire for all members of the union. This causes the return type to fall back to list<ReflectionAttribute<object>> instead of the expected list<ReflectionAttribute<T>>, producing false return.type errors in generic code.

Reproduction:

/** @template T of object */
function get(ReflectionClass|ReflectionProperty $ref, class-string<T> $class): T {
    return $ref->getAttributes($class)[0]->newInstance(); // return.type error: returns object, not T
}

Root cause

isMethodSupported() checked $methodReflection->getDeclaringClass()->getName() === $this->className. When the receiver is a union type, MethodCallReturnTypeHelper iterates per class name in the union, but the $methodReflection passed to isMethodSupported always has the same declaring class (from the first resolved member). So the extension fires for one member but not the others, and the unhandled members fall back to the stub return type.

Fix

Remove the redundant declaring class check from isMethodSupported(). The extension is already registered per-class via getClass() and only dispatched for matching classes by getDynamicMethodReturnTypeExtensionsForClass($className), so the check was unnecessary and actively harmful for union types.

Co-Authored-By: Claude Code

@janedbal
Copy link
Copy Markdown
Contributor Author

Looks like duplicate of #5463

@janedbal
Copy link
Copy Markdown
Contributor Author

Closing in favor of #5463 which fixes the root cause in MethodCallReturnTypeHelper instead of loosening the extension check.

@janedbal janedbal closed this Apr 14, 2026
@VincentLanglet
Copy link
Copy Markdown
Contributor

Closing in favor of #5463 which fixes the root cause in MethodCallReturnTypeHelper instead of loosening the extension check.

I'll need to rewrite the description cause I changed the strategy by working on ReflectionGetAttributesMethodReturnTypeExtension too

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants