diff --git a/src/Reflection/Type/UnionTypeMethodReflection.php b/src/Reflection/Type/UnionTypeMethodReflection.php index cde9bb3f69..31e73593eb 100644 --- a/src/Reflection/Type/UnionTypeMethodReflection.php +++ b/src/Reflection/Type/UnionTypeMethodReflection.php @@ -4,13 +4,13 @@ use PHPStan\Reflection\ClassMemberReflection; use PHPStan\Reflection\ClassReflection; -use PHPStan\Reflection\FunctionVariant; use PHPStan\Reflection\MethodReflection; -use PHPStan\Reflection\ParametersAcceptor; +use PHPStan\Reflection\ParametersAcceptorSelector; use PHPStan\TrinaryLogic; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; use function array_map; +use function array_merge; use function count; use function implode; @@ -74,16 +74,9 @@ public function getPrototype(): ClassMemberReflection public function getVariants(): array { - $variants = $this->methods[0]->getVariants(); - $returnType = TypeCombinator::union(...array_map(static fn (MethodReflection $method): Type => TypeCombinator::union(...array_map(static fn (ParametersAcceptor $acceptor): Type => $acceptor->getReturnType(), $method->getVariants())), $this->methods)); - - return array_map(static fn (ParametersAcceptor $acceptor): ParametersAcceptor => new FunctionVariant( - $acceptor->getTemplateTypeMap(), - $acceptor->getResolvedTemplateTypeMap(), - $acceptor->getParameters(), - $acceptor->isVariadic(), - $returnType, - ), $variants); + $variants = array_merge(...array_map(static fn (MethodReflection $method) => $method->getVariants(), $this->methods)); + + return [ParametersAcceptorSelector::combineAcceptors($variants)]; } public function isDeprecated(): TrinaryLogic diff --git a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php index a22ae889e1..ceb03b7544 100644 --- a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php @@ -2498,4 +2498,13 @@ public function testBug1517(): void $this->analyse([__DIR__ . '/data/bug-1517.php'], []); } + public function testBug7593(): void + { + $this->checkThisOnly = false; + $this->checkNullables = true; + $this->checkUnionTypes = true; + $this->checkExplicitMixed = true; + $this->analyse([__DIR__ . '/data/bug-7593.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Methods/data/bug-7593.php b/tests/PHPStan/Rules/Methods/data/bug-7593.php new file mode 100644 index 0000000000..f5424c507d --- /dev/null +++ b/tests/PHPStan/Rules/Methods/data/bug-7593.php @@ -0,0 +1,33 @@ += 8.0 + +namespace Bug7593; + +/** @template T */ +class Collection { + /** @param T $item */ + public function add(mixed $item): void {} +} + +class Foo {} +class Bar {} + +class CollectionManager +{ + /** + * @param Collection $fooCollection + * @param Collection $barCollection + */ + public function __construct( + private Collection $fooCollection, + private Collection $barCollection, + ) {} + + public function updateCollection(Foo|Bar $foobar): void + { + (match(get_class($foobar)) { + Foo::class => $this->fooCollection, + Bar::class => $this->barCollection, + default => throw new LogicException(), + })->add($foobar); + } +}