diff --git a/resources/functionMap.php b/resources/functionMap.php index bf078bc8a0..8f9d6e9bd0 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' => ['string|array|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..455962777d 100644 --- a/src/Type/Php/MbConvertEncodingFunctionReturnTypeExtension.php +++ b/src/Type/Php/MbConvertEncodingFunctionReturnTypeExtension.php @@ -5,11 +5,10 @@ use PhpParser\Node\Expr\FuncCall; use PHPStan\Analyser\Scope; use PHPStan\Reflection\FunctionReflection; -use PHPStan\Type\ArrayType; +use PHPStan\Type\Constant\ConstantBooleanType; use PHPStan\Type\DynamicFunctionReturnTypeExtension; -use PHPStan\Type\IntegerType; -use PHPStan\Type\StringType; use PHPStan\Type\Type; +use PHPStan\Type\UnionType; final class MbConvertEncodingFunctionReturnTypeExtension implements DynamicFunctionReturnTypeExtension { @@ -25,18 +24,16 @@ 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); + $argType = $scope->getType($args[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()); + if ($isString->yes() || $isArray->yes()) { + return new UnionType([$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..37ca6921f9 --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/mb_convert_encoding.php @@ -0,0 +1,25 @@ + $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|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')); +}; +