diff --git a/src/Type/IntersectionType.php b/src/Type/IntersectionType.php index f5dceab600..a300794a53 100644 --- a/src/Type/IntersectionType.php +++ b/src/Type/IntersectionType.php @@ -304,6 +304,13 @@ public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsRes static fn (Type $innerType) => $acceptingType->accepts($innerType, $strictTypes), ); + if ($result->yes()) { + $isSuperType = $acceptingType->isSuperTypeOf($this); + if ($isSuperType->no()) { + return $isSuperType->toAcceptsResult(); + } + } + if ($this->isOversizedArray()->yes()) { if (!$result->no()) { return AcceptsResult::createYes(); diff --git a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php index 9a2a8e1a9f..8c7e7a0aeb 100644 --- a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php @@ -4017,4 +4017,41 @@ public function testBug13272(): void $this->analyse([__DIR__ . '/data/bug-13272.php'], []); } + public function testBug14549(): void + { + $this->checkThisOnly = false; + $this->checkNullables = true; + $this->checkUnionTypes = true; + $this->analyse([__DIR__ . '/data/bug-14549-bis.php'], [ + [ + 'Parameter #1 $param of method Bug14549Bis\Foo::callArrayInt() expects array, array&callable given.', + 33, + ], + [ + 'Parameter #1 $param of method Bug14549Bis\Foo::callConstantArrayStringString() expects array{string, string}, array&callable(): mixed given.', + 34, + ], + [ + 'Parameter #1 $param of method Bug14549Bis\Foo::callConstantArrayObjectOrStringStringString() expects array{object|string, string, string}, array&callable(): mixed given.', + 36, + ], + [ + 'Parameter #1 $param of method Bug14549Bis\Foo::callArrayInt() expects array, array&callable given.', + 44, + ], + [ + 'Parameter #1 $param of method Bug14549Bis\Foo::callConstantArrayStringString() expects array{string, string}, array&callable(): mixed given.', + 45, + ], + [ + 'Parameter #1 $param of method Bug14549Bis\Foo::callConstantArrayObjectOrStringStringString() expects array{object|string, string, string}, array&callable(): mixed given.', + 47, + ], + [ + 'Parameter #1 $param of method Bug14549Bis\Foo::callArrayString() expects array, array given.', + 58, + ], + ]); + } + } diff --git a/tests/PHPStan/Rules/Methods/data/bug-14549-bis.php b/tests/PHPStan/Rules/Methods/data/bug-14549-bis.php new file mode 100644 index 0000000000..ea38ed6806 --- /dev/null +++ b/tests/PHPStan/Rules/Methods/data/bug-14549-bis.php @@ -0,0 +1,63 @@ + $param */ + public function callArrayInt(array $param): void + { + } + + /** @param array{string, string} $param */ + public function callConstantArrayStringString(array $param): void + { + } + + /** @param array{object|string, string} $param */ + public function callConstantArrayObjectOrStringString(array $param): void + { + } + + /** @param array{object|string, string, string} $param */ + public function callConstantArrayObjectOrStringStringString(array $param): void + { + } + + /** + * @param callable-array $task + */ + public function doCallWithCallableArray(array $task): void + { + $this->callArrayInt($task); + $this->callConstantArrayStringString($task); + $this->callConstantArrayObjectOrStringString($task); + $this->callConstantArrayObjectOrStringStringString($task); + } + + /** + * @param callable&array $task + */ + public function doCallWithCallableAndArray(array $task): void + { + $this->callArrayInt($task); + $this->callConstantArrayStringString($task); + $this->callConstantArrayObjectOrStringString($task); + $this->callConstantArrayObjectOrStringStringString($task); + } + + /** @param array $param */ + public function callArrayString(array $param): void + { + } + + public function doCallWithHasOffsetValue(array $arr): void + { + if (isset($arr[1]) && $arr[1] === 1) { + $this->callArrayString($arr); + $this->callArrayInt($arr); + } + } + +}