Skip to content

Commit 5c39df5

Browse files
committed
Fix MethodExistsTypeSpecifyingExtension for union types
1 parent 1f150cc commit 5c39df5

File tree

2 files changed

+28
-5
lines changed

2 files changed

+28
-5
lines changed

src/Type/Php/MethodExistsTypeSpecifyingExtension.php

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
use PHPStan\Type\Accessory\HasMethodType;
1515
use PHPStan\Type\ClassStringType;
1616
use PHPStan\Type\Constant\ConstantBooleanType;
17-
use PHPStan\Type\Constant\ConstantStringType;
1817
use PHPStan\Type\FunctionTypeSpecifyingExtension;
1918
use PHPStan\Type\IntersectionType;
2019
use PHPStan\Type\ObjectWithoutClassType;
@@ -50,8 +49,8 @@ public function specifyTypes(
5049
TypeSpecifierContext $context,
5150
): SpecifiedTypes
5251
{
53-
$methodNameType = $scope->getType($node->getArgs()[1]->value);
54-
if (!$methodNameType instanceof ConstantStringType) {
52+
$methodNameTypes = $scope->getType($node->getArgs()[1]->value)->getConstantStrings();
53+
if ($methodNameTypes === []) {
5554
return $this->typeSpecifier->create(
5655
new FuncCall(new FullyQualified('method_exists'), $node->getRawArgs()),
5756
new ConstantBooleanType(true),
@@ -60,14 +59,19 @@ public function specifyTypes(
6059
);
6160
}
6261

62+
$hasMethodTypes = [];
63+
foreach ($methodNameTypes as $methodNameType) {
64+
$hasMethodTypes[] = new HasMethodType($methodNameType->getValue());
65+
}
66+
6367
$objectType = $scope->getType($node->getArgs()[0]->value);
6468
if ($objectType->isString()->yes()) {
6569
if ($objectType->isClassString()->yes()) {
6670
return $this->typeSpecifier->create(
6771
$node->getArgs()[0]->value,
6872
new IntersectionType([
6973
$objectType,
70-
new HasMethodType($methodNameType->getValue()),
74+
...$hasMethodTypes,
7175
]),
7276
$context,
7377
$scope,
@@ -82,7 +86,7 @@ public function specifyTypes(
8286
new UnionType([
8387
new IntersectionType([
8488
new ObjectWithoutClassType(),
85-
new HasMethodType($methodNameType->getValue()),
89+
...$hasMethodTypes,
8690
]),
8791
new ClassStringType(),
8892
]),
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace Bug13272;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
function foo(object $bar): void
8+
{
9+
foreach (['qux', 'quux'] as $method) {
10+
assertType("'quux'|'qux'", $method);
11+
12+
if (!method_exists($bar, $method)) {
13+
throw new \Exception;
14+
}
15+
16+
assertType("'quux'|'qux'", $method);
17+
assertType("object&hasMethod(quux)&hasMethod(qux)", $bar);
18+
}
19+
}

0 commit comments

Comments
 (0)