diff --git a/resources/functionMap_php82delta.php b/resources/functionMap_php82delta.php new file mode 100644 index 0000000000..72c613a4d8 --- /dev/null +++ b/resources/functionMap_php82delta.php @@ -0,0 +1,29 @@ + [ + 'str_split' => ['array', 'str'=>'string', 'split_length='=>'positive-int'], + ], + 'old' => [ + + ] +]; diff --git a/src/Php/PhpVersion.php b/src/Php/PhpVersion.php index 89dc2dddc7..d9c63aa40d 100644 --- a/src/Php/PhpVersion.php +++ b/src/Php/PhpVersion.php @@ -196,4 +196,9 @@ public function deprecatesDynamicProperties(): bool return $this->versionId >= 80200; } + public function strSplitReturnsEmptyArray(): bool + { + return $this->versionId >= 80200; + } + } diff --git a/src/Reflection/SignatureMap/FunctionSignatureMapProvider.php b/src/Reflection/SignatureMap/FunctionSignatureMapProvider.php index 6789bb7833..cc9a8a347f 100644 --- a/src/Reflection/SignatureMap/FunctionSignatureMapProvider.php +++ b/src/Reflection/SignatureMap/FunctionSignatureMapProvider.php @@ -204,6 +204,15 @@ public function getSignatureMap(): array $signatureMap = $this->computeSignatureMap($signatureMap, $php81MapDelta); } + if ($this->phpVersion->getVersionId() >= 80200) { + $php82MapDelta = require __DIR__ . '/../../../resources/functionMap_php82delta.php'; + if (!is_array($php82MapDelta)) { + throw new ShouldNotHappenException('Signature map could not be loaded.'); + } + + $signatureMap = $this->computeSignatureMap($signatureMap, $php82MapDelta); + } + $this->signatureMap = $signatureMap; } diff --git a/src/Type/Php/StrSplitFunctionReturnTypeExtension.php b/src/Type/Php/StrSplitFunctionReturnTypeExtension.php index a3986fafb5..a61c897864 100644 --- a/src/Type/Php/StrSplitFunctionReturnTypeExtension.php +++ b/src/Type/Php/StrSplitFunctionReturnTypeExtension.php @@ -90,7 +90,7 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, $stringType = $scope->getType($functionCall->getArgs()[0]->value); - return TypeTraverser::map($stringType, static function (Type $type, callable $traverse) use ($encoding, $splitLength, $scope): Type { + return TypeTraverser::map($stringType, function (Type $type, callable $traverse) use ($encoding, $splitLength, $scope): Type { if ($type instanceof UnionType || $type instanceof IntersectionType) { return $traverse($type); } @@ -98,7 +98,7 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, if (!$type instanceof ConstantStringType) { $returnType = new ArrayType(new IntegerType(), new StringType()); - return $encoding === null + return $encoding === null && !$this->phpVersion->strSplitReturnsEmptyArray() ? TypeCombinator::intersect($returnType, new NonEmptyArrayType()) : $returnType; } diff --git a/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php b/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php index 8ce2b2fa38..6d45933547 100644 --- a/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php @@ -5138,6 +5138,14 @@ public function testArrayFunctions( public function dataFunctions(): array { + $strSplitDefaultReturnType = 'non-empty-array|false'; + if (PHP_VERSION_ID >= 80000) { + $strSplitDefaultReturnType = 'non-empty-array'; + } + if (PHP_VERSION_ID >= 80200) { + $strSplitDefaultReturnType = 'array'; + } + return [ [ 'string', @@ -5328,7 +5336,7 @@ public function dataFunctions(): array '$gettimeofdayBenevolent', ], [ - PHP_VERSION_ID < 80000 ? 'non-empty-array|false' : 'non-empty-array', + $strSplitDefaultReturnType, '$strSplitConstantStringWithoutDefinedParameters', ], [ @@ -5336,7 +5344,7 @@ public function dataFunctions(): array '$strSplitConstantStringWithoutDefinedSplitLength', ], [ - 'non-empty-array', + PHP_VERSION_ID < 80200 ? 'non-empty-array' : 'array', '$strSplitStringWithoutDefinedSplitLength', ], [ @@ -5352,7 +5360,7 @@ public function dataFunctions(): array '$strSplitConstantStringWithFailureSplitLength', ], [ - PHP_VERSION_ID < 80000 ? 'non-empty-array|false' : 'non-empty-array', + $strSplitDefaultReturnType, '$strSplitConstantStringWithInvalidSplitLengthType', ], [ @@ -5360,7 +5368,7 @@ public function dataFunctions(): array '$strSplitConstantStringWithVariableStringAndConstantSplitLength', ], [ - PHP_VERSION_ID < 80000 ? 'non-empty-array|false' : 'non-empty-array', + $strSplitDefaultReturnType, '$strSplitConstantStringWithVariableStringAndVariableSplitLength', ], // parse_url