From 026cb298a7368caf2e51b4cb8d6d509f7896cd53 Mon Sep 17 00:00:00 2001 From: Jack Worman Date: Sat, 21 Dec 2024 13:49:30 -0500 Subject: [PATCH] mb_convert_encoding-can-return-false --- resources/functionMap.php | 2 +- ...ertEncodingFunctionReturnTypeExtension.php | 19 ++++++--------- tests/PHPStan/Analyser/nsrt/bug-3336.php | 10 -------- .../Analyser/nsrt/mb_convert_encoding.php | 24 +++++++++++++++++++ 4 files changed, 32 insertions(+), 23 deletions(-) delete mode 100644 tests/PHPStan/Analyser/nsrt/bug-3336.php create mode 100644 tests/PHPStan/Analyser/nsrt/mb_convert_encoding.php diff --git a/resources/functionMap.php b/resources/functionMap.php index bf078bc8a0..d44a046b07 100644 --- a/resources/functionMap.php +++ b/resources/functionMap.php @@ -6312,7 +6312,7 @@ 'mb_check_encoding' => ['bool', 'var='=>'string|array', 'encoding='=>'string'], 'mb_chr' => ['string|false', 'cp'=>'int', 'encoding='=>'string'], 'mb_convert_case' => ['string', 'sourcestring'=>'string', 'mode'=>'int', 'encoding='=>'string'], -'mb_convert_encoding' => ['string|array|false', 'val'=>'string|array', 'to_encoding'=>'string', 'from_encoding='=>'mixed'], +'mb_convert_encoding' => ['__benevolent>|false>', 'val'=>'string|array>', 'to_encoding'=>'string', 'from_encoding='=>'mixed'], 'mb_convert_kana' => ['string', 'str'=>'string', 'option='=>'string', 'encoding='=>'string'], 'mb_convert_variables' => ['string|false', 'to_encoding'=>'string', 'from_encoding'=>'array|string', '&rw_vars'=>'string|array|object', '&...rw_vars='=>'string|array|object'], 'mb_decode_mimeheader' => ['string', 'string'=>'string'], diff --git a/src/Type/Php/MbConvertEncodingFunctionReturnTypeExtension.php b/src/Type/Php/MbConvertEncodingFunctionReturnTypeExtension.php index dd46ed4c2a..2fbef61667 100644 --- a/src/Type/Php/MbConvertEncodingFunctionReturnTypeExtension.php +++ b/src/Type/Php/MbConvertEncodingFunctionReturnTypeExtension.php @@ -5,10 +5,9 @@ use PhpParser\Node\Expr\FuncCall; use PHPStan\Analyser\Scope; use PHPStan\Reflection\FunctionReflection; -use PHPStan\Type\ArrayType; +use PHPStan\Type\BenevolentUnionType; +use PHPStan\Type\Constant\ConstantBooleanType; use PHPStan\Type\DynamicFunctionReturnTypeExtension; -use PHPStan\Type\IntegerType; -use PHPStan\Type\StringType; use PHPStan\Type\Type; final class MbConvertEncodingFunctionReturnTypeExtension implements DynamicFunctionReturnTypeExtension @@ -25,18 +24,14 @@ public function getTypeFromFunctionCall( Scope $scope, ): ?Type { - if (!isset($functionCall->getArgs()[0])) { + $args = $functionCall->getArgs(); + if (!isset($args[0])) { return null; } - $argType = $scope->getType($functionCall->getArgs()[0]->value); - $isString = $argType->isString(); - $isArray = $argType->isArray(); - $compare = $isString->compareTo($isArray); - if ($compare === $isString) { - return new StringType(); - } elseif ($compare === $isArray) { - return new ArrayType(new IntegerType(), new StringType()); + $argType = $scope->getType($args[0]->value); + if ($argType->isString()->yes() || $argType->isArray()->yes()) { + return new BenevolentUnionType([$argType, new ConstantBooleanType(false)]); } return null; diff --git a/tests/PHPStan/Analyser/nsrt/bug-3336.php b/tests/PHPStan/Analyser/nsrt/bug-3336.php deleted file mode 100644 index a6712e6f69..0000000000 --- a/tests/PHPStan/Analyser/nsrt/bug-3336.php +++ /dev/null @@ -1,10 +0,0 @@ -', mb_convert_encoding($arr)); - \PHPStan\Testing\assertType('string', mb_convert_encoding($str)); - \PHPStan\Testing\assertType('array|string|false', mb_convert_encoding($mixed)); - \PHPStan\Testing\assertType('array|string|false', mb_convert_encoding()); -}; diff --git a/tests/PHPStan/Analyser/nsrt/mb_convert_encoding.php b/tests/PHPStan/Analyser/nsrt/mb_convert_encoding.php new file mode 100644 index 0000000000..30b949f270 --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/mb_convert_encoding.php @@ -0,0 +1,24 @@ + $stringList + * @param list $intList + */ +function test_mb_convert_encoding( + mixed $mixed, + string $string, + array $mixedArray, + array $structuredArray, + array $stringList, + array $intList, +): void { + \PHPStan\Testing\assertType('(array|bool|float|int|string|null>|string|false)', mb_convert_encoding($mixed, 'UTF-8')); + \PHPStan\Testing\assertType('(string|false)', mb_convert_encoding($string, 'UTF-8')); + \PHPStan\Testing\assertType('(array|false)', mb_convert_encoding($mixedArray, 'UTF-8')); + \PHPStan\Testing\assertType('(array{foo: string, bar: int}|false)', mb_convert_encoding($structuredArray, 'UTF-8')); + \PHPStan\Testing\assertType('(list|false)', mb_convert_encoding($stringList, 'UTF-8')); + \PHPStan\Testing\assertType('(list|false)', mb_convert_encoding($intList, 'UTF-8')); +};