From 65be2b21be5614c7a1d8841a0381fcfb7a1330b8 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Tue, 7 Jan 2025 11:40:15 +0100 Subject: [PATCH] Support arrays with union value-types in `implode()` --- phpstan-baseline.neon | 5 ---- .../ImplodeFunctionReturnTypeExtension.php | 23 +++++++++++--- tests/PHPStan/Analyser/nsrt/bug-11854.php | 18 +++++++++++ tests/PHPStan/Analyser/nsrt/implode.php | 30 +++++++++++++++++++ 4 files changed, 67 insertions(+), 9 deletions(-) create mode 100644 tests/PHPStan/Analyser/nsrt/bug-11854.php diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 9977a1992d..93649e9087 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1362,11 +1362,6 @@ parameters: count: 1 path: src/Type/Php/FunctionExistsFunctionTypeSpecifyingExtension.php - - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" - count: 1 - path: src/Type/Php/ImplodeFunctionReturnTypeExtension.php - - message: """ #^Call to deprecated method getConstantScalars\\(\\) of class PHPStan\\\\Type\\\\TypeUtils\\: diff --git a/src/Type/Php/ImplodeFunctionReturnTypeExtension.php b/src/Type/Php/ImplodeFunctionReturnTypeExtension.php index 5c680b5b62..a052a43416 100644 --- a/src/Type/Php/ImplodeFunctionReturnTypeExtension.php +++ b/src/Type/Php/ImplodeFunctionReturnTypeExtension.php @@ -4,7 +4,9 @@ use PhpParser\Node\Expr\FuncCall; use PHPStan\Analyser\Scope; +use PHPStan\Internal\CombinationsHelper; use PHPStan\Reflection\FunctionReflection; +use PHPStan\Reflection\InitializerExprTypeResolver; use PHPStan\Type\Accessory\AccessoryLiteralStringType; use PHPStan\Type\Accessory\AccessoryLowercaseStringType; use PHPStan\Type\Accessory\AccessoryNonEmptyStringType; @@ -12,7 +14,6 @@ use PHPStan\Type\Accessory\AccessoryUppercaseStringType; use PHPStan\Type\Constant\ConstantArrayType; use PHPStan\Type\Constant\ConstantStringType; -use PHPStan\Type\ConstantScalarType; use PHPStan\Type\DynamicFunctionReturnTypeExtension; use PHPStan\Type\IntersectionType; use PHPStan\Type\StringType; @@ -114,14 +115,28 @@ private function inferConstantType(ConstantArrayType $arrayType, ConstantStringT $valueTypes = $array->getValueTypes(); $arrayValues = []; + $combinationsCount = 1; foreach ($valueTypes as $valueType) { - if (!$valueType instanceof ConstantScalarType) { + $constScalars = $valueType->getConstantScalarValues(); + if (count($constScalars) === 0) { return null; } - $arrayValues[] = $valueType->getValue(); + $arrayValues[] = $constScalars; + $combinationsCount *= count($constScalars); } - $strings[] = new ConstantStringType(implode($separatorType->getValue(), $arrayValues)); + if ($combinationsCount > InitializerExprTypeResolver::CALCULATE_SCALARS_LIMIT) { + return null; + } + + $combinations = CombinationsHelper::combinations($arrayValues); + foreach ($combinations as $combination) { + $strings[] = new ConstantStringType(implode($separatorType->getValue(), $combination)); + } + } + + if (count($strings) > InitializerExprTypeResolver::CALCULATE_SCALARS_LIMIT) { + return null; } return TypeCombinator::union(...$strings); diff --git a/tests/PHPStan/Analyser/nsrt/bug-11854.php b/tests/PHPStan/Analyser/nsrt/bug-11854.php new file mode 100644 index 0000000000..48a49258cc --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-11854.php @@ -0,0 +1,18 @@ +