From 57017d54bd1c266264bc71aa5aea7fd6ea37f184 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 25 Dec 2025 17:05:54 +0100 Subject: [PATCH 1/5] TypeCombinator: Prevent unnecessary work --- src/Type/TypeCombinator.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Type/TypeCombinator.php b/src/Type/TypeCombinator.php index 0d6ef1cb4c..6170f00278 100644 --- a/src/Type/TypeCombinator.php +++ b/src/Type/TypeCombinator.php @@ -810,11 +810,11 @@ private static function processArrayTypes(array $arrayTypes): array continue; } - $constantArrays = $arrayType->getConstantArrays(); foreach ($constantArrays as $constantArray) { + $valueTypes = $constantArray->getValueTypes(); foreach ($constantArray->getKeyTypes() as $i => $keyType) { $keyTypesForGeneralArray[] = $keyType; - $valueTypesForGeneralArray[] = $constantArray->getValueTypes()[$i]; + $valueTypesForGeneralArray[] = $valueTypes[$i]; $keyTypeValue = $keyType->getValue(); if (array_key_exists($keyTypeValue, $constantKeyTypesNumbered)) { From 41fc5a5f8ddb1f3b3182d7da02197f4b364d5f5b Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 25 Dec 2025 17:12:00 +0100 Subject: [PATCH 2/5] remove unncessary array_map() --- src/Type/TypeCombinator.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Type/TypeCombinator.php b/src/Type/TypeCombinator.php index 6170f00278..44caf920cb 100644 --- a/src/Type/TypeCombinator.php +++ b/src/Type/TypeCombinator.php @@ -789,13 +789,9 @@ private static function processArrayTypes(array $arrayTypes): array /** @var int|float $nextConstantKeyTypeIndex */ $nextConstantKeyTypeIndex = 1; - $constantArraysMap = array_map( - static fn (Type $t) => $t->getConstantArrays(), - $arrayTypes, - ); - foreach ($arrayTypes as $arrayIdx => $arrayType) { - $constantArrays = $constantArraysMap[$arrayIdx]; + foreach ($arrayTypes as $arrayType) { + $constantArrays = $arrayType->getConstantArrays(); $isConstantArray = $constantArrays !== []; if (!$isConstantArray || !$arrayType->isIterableAtLeastOnce()->no()) { $filledArrays++; From 13ea85553205721cf5760e3d4554dea28b4a8ec6 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 25 Dec 2025 17:17:06 +0100 Subject: [PATCH 3/5] use foreach over slower array_map() --- src/Type/TypeCombinator.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Type/TypeCombinator.php b/src/Type/TypeCombinator.php index 44caf920cb..c9d4966f33 100644 --- a/src/Type/TypeCombinator.php +++ b/src/Type/TypeCombinator.php @@ -27,7 +27,6 @@ use PHPStan\Type\Generic\TemplateUnionType; use function array_key_exists; use function array_key_first; -use function array_map; use function array_merge; use function array_slice; use function array_splice; @@ -867,11 +866,10 @@ private static function processArrayTypes(array $arrayTypes): array } $reducedArrayTypes = self::reduceArrays($arrayTypes, true); - - return array_map( - static fn (Type $arrayType) => self::intersect($arrayType, ...$accessoryTypes), - self::optimizeConstantArrays($reducedArrayTypes), - ); + foreach (self::optimizeConstantArrays($reducedArrayTypes) as $idx => $reducedArray) { + $reducedArrayTypes[$idx] = self::intersect($reducedArray, ...$accessoryTypes); + } + return $reducedArrayTypes; } /** From 04ba277270ead7e6fbc12697441bdbf8fb13404d Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 25 Dec 2025 17:27:43 +0100 Subject: [PATCH 4/5] move method call out of loop --- src/Type/TypeCombinator.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Type/TypeCombinator.php b/src/Type/TypeCombinator.php index c9d4966f33..a6e646293f 100644 --- a/src/Type/TypeCombinator.php +++ b/src/Type/TypeCombinator.php @@ -903,6 +903,7 @@ private static function optimizeConstantArrays(array $types): array $valueTypes = []; $keyTypes = []; $nextAutoIndex = 0; + $innerValueTypes = $type->getValueTypes(); foreach ($type->getKeyTypes() as $i => $innerKeyType) { if (!$innerKeyType instanceof ConstantIntegerType) { $isList = false; @@ -916,8 +917,7 @@ private static function optimizeConstantArrays(array $types): array $generalizedKeyType = $innerKeyType->generalize(GeneralizePrecision::moreSpecific()); $keyTypes[$generalizedKeyType->describe(VerbosityLevel::precise())] = $generalizedKeyType; - $innerValueType = $type->getValueTypes()[$i]; - $generalizedValueType = TypeTraverser::map($innerValueType, static function (Type $type) use ($traverse): Type { + $generalizedValueType = TypeTraverser::map($innerValueTypes[$i], static function (Type $type) use ($traverse): Type { if ($type instanceof ArrayType || $type instanceof ConstantArrayType) { return TypeCombinator::intersect($type, new OversizedArrayType()); } From d6043022c678e2395c04ed15788b3d04a52b787f Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 25 Dec 2025 17:42:40 +0100 Subject: [PATCH 5/5] Update TypeCombinator.php --- src/Type/TypeCombinator.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Type/TypeCombinator.php b/src/Type/TypeCombinator.php index a6e646293f..f8f1f7e4ed 100644 --- a/src/Type/TypeCombinator.php +++ b/src/Type/TypeCombinator.php @@ -865,8 +865,8 @@ private static function processArrayTypes(array $arrayTypes): array ]; } - $reducedArrayTypes = self::reduceArrays($arrayTypes, true); - foreach (self::optimizeConstantArrays($reducedArrayTypes) as $idx => $reducedArray) { + $reducedArrayTypes = self::optimizeConstantArrays(self::reduceArrays($arrayTypes, true)); + foreach ($reducedArrayTypes as $idx => $reducedArray) { $reducedArrayTypes[$idx] = self::intersect($reducedArray, ...$accessoryTypes); } return $reducedArrayTypes;