Skip to content

Commit c5049d1

Browse files
Use intersection
1 parent a27e585 commit c5049d1

2 files changed

Lines changed: 23 additions & 10 deletions

File tree

src/Type/IntersectionType.php

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace PHPStan\Type;
44

5+
use PHPStan\Internal\CombinationsHelper;
56
use PHPStan\Php\PhpVersion;
67
use PHPStan\PhpDocParser\Ast\Type\ArrayShapeNode;
78
use PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;
@@ -16,6 +17,7 @@
1617
use PHPStan\Reflection\MissingConstantFromReflectionException;
1718
use PHPStan\Reflection\MissingMethodFromReflectionException;
1819
use PHPStan\Reflection\MissingPropertyFromReflectionException;
20+
use PHPStan\Reflection\ParametersAcceptorSelector;
1921
use PHPStan\Reflection\Type\IntersectionTypeUnresolvedMethodPrototypeReflection;
2022
use PHPStan\Reflection\Type\IntersectionTypeUnresolvedPropertyPrototypeReflection;
2123
use PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection;
@@ -1141,14 +1143,20 @@ public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope)
11411143
}
11421144

11431145
if (count($yesAcceptors) > 0) {
1144-
return array_merge(...$yesAcceptors);
1146+
$acceptors = $yesAcceptors;
1147+
} elseif(count($maybeAcceptors) > 0) {
1148+
$acceptors = $maybeAcceptors;
1149+
} else {
1150+
throw new ShouldNotHappenException();
11451151
}
11461152

1147-
if (count($maybeAcceptors) > 0) {
1148-
return array_merge(...$maybeAcceptors);
1153+
$result = [];
1154+
$combinations = CombinationsHelper::combinations($acceptors);
1155+
foreach ($combinations as $combination) {
1156+
$result[] = ParametersAcceptorSelector::combineAcceptors($combination);
11491157
}
11501158

1151-
throw new ShouldNotHappenException();
1159+
return $result;
11521160
}
11531161

11541162
public function isCloneable(): TrinaryLogic

tests/PHPStan/Analyser/nsrt/bug-14362.php

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,23 +37,28 @@ public function __invoke(B $b): int {
3737
}
3838

3939
interface E
40+
{
41+
public function __invoke(B $b, bool $option = true): int;
42+
}
43+
44+
interface F
4045
{
4146

4247
}
4348

4449
class G {
45-
public static function u(): A&B&E {
46-
return new class() implements A, B, E {
47-
public function __invoke(B $b): int {
50+
public static function u(): A&E {
51+
return new class() implements A, E {
52+
public function __invoke(B $b, bool $option = true): int {
4853
return 1;
4954
}
5055
};
5156
}
5257
}
5358

5459
class H {
55-
public static function u(): B&E {
56-
return new class() implements B, E {
60+
public static function u(): B&F {
61+
return new class() implements B, F {
5762
};
5863
}
5964
}
@@ -63,7 +68,7 @@ function doBar() : void {
6368
assertType('Closure(Bug14362\B): int', D::u()(...));
6469

6570
// Intersection with one yes-callable and multiple maybe-callable types
66-
assertType('Closure(Bug14362\B): int', G::u()(...));
71+
assertType('Closure(Bug14362\B, bool=): int', G::u()(...));
6772

6873
// Intersection with only maybe-callable types (neither has __invoke)
6974
assertType('Closure', H::u()(...));

0 commit comments

Comments
 (0)