Skip to content

Commit

Permalink
Fix resolving variants for union type methods
Browse files Browse the repository at this point in the history
  • Loading branch information
Richard van Velzen authored and ondrejmirtes committed Aug 1, 2022
1 parent d0c048c commit 39380cd
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 12 deletions.
17 changes: 5 additions & 12 deletions src/Reflection/Type/UnionTypeMethodReflection.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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'], []);
}

}
33 changes: 33 additions & 0 deletions tests/PHPStan/Rules/Methods/data/bug-7593.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php declare(strict_types = 1); // lint >= 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<Foo> $fooCollection
* @param Collection<Bar> $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);
}
}

0 comments on commit 39380cd

Please sign in to comment.