diff --git a/src/Rules/MissingTypehintCheck.php b/src/Rules/MissingTypehintCheck.php index dd0d451478..0a2791b234 100644 --- a/src/Rules/MissingTypehintCheck.php +++ b/src/Rules/MissingTypehintCheck.php @@ -76,7 +76,11 @@ public function getIterableTypesWithMissingValueTypehint(Type $type): array if ($iterableValue instanceof MixedType && !$iterableValue->isExplicitMixed()) { $iterablesWithMissingValueTypehint[] = $type; } - if ($type instanceof IntersectionType && !$type->isList()->yes()) { + if ($type instanceof IntersectionType) { + if ($type->isList()->yes()) { + return $traverse($type->getIterableValueType()); + } + return $type; } } diff --git a/tests/PHPStan/Rules/PhpDoc/FunctionAssertRuleTest.php b/tests/PHPStan/Rules/PhpDoc/FunctionAssertRuleTest.php index 72c49cc286..5af9a8aae4 100644 --- a/tests/PHPStan/Rules/PhpDoc/FunctionAssertRuleTest.php +++ b/tests/PHPStan/Rules/PhpDoc/FunctionAssertRuleTest.php @@ -69,6 +69,11 @@ public function testRule(): void 'Asserted negated type string for $i with type int does not narrow down the type.', 70, ], + [ + 'PHPDoc tag @phpstan-assert for $array has no value type specified in iterable type array.', + 88, + 'See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type', + ], ]); } diff --git a/tests/PHPStan/Rules/PhpDoc/data/function-assert.php b/tests/PHPStan/Rules/PhpDoc/data/function-assert.php index e1b25eb6c0..d35c1b3b5b 100644 --- a/tests/PHPStan/Rules/PhpDoc/data/function-assert.php +++ b/tests/PHPStan/Rules/PhpDoc/data/function-assert.php @@ -76,3 +76,18 @@ function negate1(int $i): void function negate2(int $i): void { } + +/** + * @param array $array + * @param string $message + * + * @phpstan-impure + * + * @psalm-assert list $array + */ +function isList($array, $message = ''): void +{ + if (!array_is_list($array)) { + + } +}