From c911905592a0de108f90c4f21e74ae8cc30cde54 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Fri, 15 Oct 2021 18:11:52 +0200 Subject: [PATCH 1/6] More precise signatures for mb_* functions --- resources/functionMap.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/resources/functionMap.php b/resources/functionMap.php index 287e44428f..a0e7df961f 100644 --- a/resources/functionMap.php +++ b/resources/functionMap.php @@ -6345,18 +6345,18 @@ 'mb_split' => ['array|false', 'pattern'=>'string', 'string'=>'string', 'limit='=>'int'], 'mb_strcut' => ['string', 'str'=>'string', 'start'=>'int', 'length='=>'?int', 'encoding='=>'string'], 'mb_strimwidth' => ['string', 'str'=>'string', 'start'=>'int', 'width'=>'int', 'trimmarker='=>'string', 'encoding='=>'string'], -'mb_stripos' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int', 'encoding='=>'string'], +'mb_stripos' => ['0|positive-int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int', 'encoding='=>'string'], 'mb_stristr' => ['string|false', 'haystack'=>'string', 'needle'=>'string', 'part='=>'bool', 'encoding='=>'string'], -'mb_strlen' => ['int|false', 'str'=>'string', 'encoding='=>'string'], -'mb_strpos' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int', 'encoding='=>'string'], +'mb_strlen' => ['0|positive-int|false', 'str'=>'string', 'encoding='=>'string'], +'mb_strpos' => ['0|positive-int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int', 'encoding='=>'string'], 'mb_strrchr' => ['string|false', 'haystack'=>'string', 'needle'=>'string', 'part='=>'bool', 'encoding='=>'string'], 'mb_strrichr' => ['string|false', 'haystack'=>'string', 'needle'=>'string', 'part='=>'bool', 'encoding='=>'string'], -'mb_strripos' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int', 'encoding='=>'string'], -'mb_strrpos' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int', 'encoding='=>'string'], +'mb_strripos' => ['0|positive-int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int', 'encoding='=>'string'], +'mb_strrpos' => ['0|positive-int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int', 'encoding='=>'string'], 'mb_strstr' => ['string|false', 'haystack'=>'string', 'needle'=>'string', 'part='=>'bool', 'encoding='=>'string'], 'mb_strtolower' => ['string', 'str'=>'string', 'encoding='=>'string'], 'mb_strtoupper' => ['string', 'str'=>'string', 'encoding='=>'string'], -'mb_strwidth' => ['int', 'str'=>'string', 'encoding='=>'string'], +'mb_strwidth' => ['0|positive-int', 'str'=>'string', 'encoding='=>'string'], 'mb_substitute_character' => ['mixed', 'substchar='=>'mixed'], 'mb_substr' => ['string', 'str'=>'string', 'start'=>'int', 'length='=>'?int', 'encoding='=>'string'], 'mb_substr_count' => ['0|positive-int', 'haystack'=>'string', 'needle'=>'string', 'encoding='=>'string'], From 34e95355dfa02ddc921485283daa021e757ba784 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Fri, 15 Oct 2021 18:17:41 +0200 Subject: [PATCH 2/6] fix --- tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php b/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php index 9fb4ac824e..92bdde96ae 100644 --- a/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php @@ -5302,15 +5302,15 @@ public function dataFunctions(): array '$versionCompare8', ], [ - 'int', + 'int<0, max>', '$mbStrlenWithoutEncoding', ], [ - 'int', + 'int<0, max>', '$mbStrlenWithValidEncoding', ], [ - 'int', + 'int<0, max>', '$mbStrlenWithValidEncodingAlias', ], [ @@ -5318,11 +5318,11 @@ public function dataFunctions(): array '$mbStrlenWithInvalidEncoding', ], [ - PHP_VERSION_ID < 80000 ? 'int|false' : 'int', + PHP_VERSION_ID < 80000 ? 'int<0, max>|false' : 'int<0, max>', '$mbStrlenWithValidAndInvalidEncoding', ], [ - PHP_VERSION_ID < 80000 ? 'int|false' : 'int', + PHP_VERSION_ID < 80000 ? 'int<0, max>|false' : 'int<0, max>', '$mbStrlenWithUnknownEncoding', ], [ From e73464d63b849d31ed3c08f09c5f97ca1be5c6e1 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Tue, 1 Feb 2022 12:50:54 +0100 Subject: [PATCH 3/6] php8 fix --- src/Type/Php/MbFunctionsReturnTypeExtension.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Type/Php/MbFunctionsReturnTypeExtension.php b/src/Type/Php/MbFunctionsReturnTypeExtension.php index ad3115da25..7644e23cc3 100644 --- a/src/Type/Php/MbFunctionsReturnTypeExtension.php +++ b/src/Type/Php/MbFunctionsReturnTypeExtension.php @@ -11,6 +11,7 @@ use PHPStan\Type\Constant\ConstantBooleanType; use PHPStan\Type\Constant\ConstantStringType; use PHPStan\Type\DynamicFunctionReturnTypeExtension; +use PHPStan\Type\IntegerRangeType; use PHPStan\Type\StringType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; @@ -74,6 +75,11 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, $returnType = ParametersAcceptorSelector::selectSingle($functionReflection->getVariants())->getReturnType(); $positionEncodingParam = $this->encodingPositionMap[$functionReflection->getName()]; + // php8-stubs define a regular int return-type for mb_strlen. use a more precise type instead. + if ($functionReflection->getName() === 'mb_strlen') { + $returnType = IntegerRangeType::fromInterval(0, null); + } + if (count($functionCall->getArgs()) < $positionEncodingParam) { return TypeCombinator::remove($returnType, new BooleanType()); } From d98691de319c2126f394b3812e6f89f11a1716ee Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Tue, 1 Feb 2022 13:47:34 +0100 Subject: [PATCH 4/6] fix --- src/Type/Php/MbFunctionsReturnTypeExtension.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Type/Php/MbFunctionsReturnTypeExtension.php b/src/Type/Php/MbFunctionsReturnTypeExtension.php index 7644e23cc3..ca90745d0c 100644 --- a/src/Type/Php/MbFunctionsReturnTypeExtension.php +++ b/src/Type/Php/MbFunctionsReturnTypeExtension.php @@ -77,7 +77,10 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, // php8-stubs define a regular int return-type for mb_strlen. use a more precise type instead. if ($functionReflection->getName() === 'mb_strlen') { - $returnType = IntegerRangeType::fromInterval(0, null); + $returnType = TypeCombinator::union([ + IntegerRangeType::fromInterval(0, null), + new ConstantBooleanType(false), + ]); } if (count($functionCall->getArgs()) < $positionEncodingParam) { From 485558868c320e86535e2c3fe201d89efa4599bb Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Tue, 1 Feb 2022 13:55:24 +0100 Subject: [PATCH 5/6] fix --- resources/functionMap_php80delta.php | 2 ++ src/Type/Php/MbFunctionsReturnTypeExtension.php | 8 -------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/resources/functionMap_php80delta.php b/resources/functionMap_php80delta.php index d260510eca..e1ef73a8ca 100644 --- a/resources/functionMap_php80delta.php +++ b/resources/functionMap_php80delta.php @@ -75,6 +75,7 @@ 'ldap_set_rebind_proc' => ['bool', 'ldap'=>'resource', 'callback'=>'?callable'], 'mb_decode_numericentity' => ['string|false', 'string'=>'string', 'convmap'=>'array', 'encoding='=>'string'], 'mb_str_split' => ['non-empty-array', 'str'=>'string', 'split_length='=>'positive-int', 'encoding='=>'string'], + 'mb_strlen' => ['0|positive-int', 'str'=>'string', 'encoding='=>'string'], 'mktime' => ['int|false', 'hour'=>'int', 'minute='=>'int', 'second='=>'int', 'month='=>'int', 'day='=>'int', 'year='=>'int'], 'odbc_exec' => ['resource|false', 'connection_id'=>'resource', 'query'=>'string'], 'parse_str' => ['void', 'encoded_string'=>'string', '&w_result'=>'array'], @@ -206,6 +207,7 @@ 'ldap_sort' => ['bool', 'link_identifier'=>'resource', 'result_identifier'=>'resource', 'sortfilter'=>'string'], 'mb_decode_numericentity' => ['string|false', 'string'=>'string', 'convmap'=>'array', 'encoding='=>'string', 'is_hex='=>'bool'], 'mktime' => ['int|false', 'hour='=>'int', 'minute='=>'int', 'second='=>'int', 'month='=>'int', 'day='=>'int', 'year='=>'int'], + 'mb_strlen' => ['0|positive-int', 'str'=>'string', 'encoding='=>'string'], 'odbc_exec' => ['resource|false', 'connection_id'=>'resource', 'query'=>'string', 'flags='=>'int'], 'parse_str' => ['void', 'encoded_string'=>'string', '&w_result='=>'array'], 'password_hash' => ['string|false|null', 'password'=>'string', 'algo'=>'?string|?int', 'options='=>'array'], diff --git a/src/Type/Php/MbFunctionsReturnTypeExtension.php b/src/Type/Php/MbFunctionsReturnTypeExtension.php index ca90745d0c..3b2b01f7c7 100644 --- a/src/Type/Php/MbFunctionsReturnTypeExtension.php +++ b/src/Type/Php/MbFunctionsReturnTypeExtension.php @@ -75,14 +75,6 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, $returnType = ParametersAcceptorSelector::selectSingle($functionReflection->getVariants())->getReturnType(); $positionEncodingParam = $this->encodingPositionMap[$functionReflection->getName()]; - // php8-stubs define a regular int return-type for mb_strlen. use a more precise type instead. - if ($functionReflection->getName() === 'mb_strlen') { - $returnType = TypeCombinator::union([ - IntegerRangeType::fromInterval(0, null), - new ConstantBooleanType(false), - ]); - } - if (count($functionCall->getArgs()) < $positionEncodingParam) { return TypeCombinator::remove($returnType, new BooleanType()); } From c314be4f1beb70486dc9a7370ab9ce4ed5048a03 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Tue, 1 Feb 2022 14:19:35 +0100 Subject: [PATCH 6/6] cs --- src/Type/Php/MbFunctionsReturnTypeExtension.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Type/Php/MbFunctionsReturnTypeExtension.php b/src/Type/Php/MbFunctionsReturnTypeExtension.php index 3b2b01f7c7..ad3115da25 100644 --- a/src/Type/Php/MbFunctionsReturnTypeExtension.php +++ b/src/Type/Php/MbFunctionsReturnTypeExtension.php @@ -11,7 +11,6 @@ use PHPStan\Type\Constant\ConstantBooleanType; use PHPStan\Type\Constant\ConstantStringType; use PHPStan\Type\DynamicFunctionReturnTypeExtension; -use PHPStan\Type\IntegerRangeType; use PHPStan\Type\StringType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator;