Skip to content

Commit 4dfbe16

Browse files
committed
Optimization of huge unions of oversized arrays
1 parent c04555b commit 4dfbe16

File tree

1 file changed

+37
-3
lines changed

1 file changed

+37
-3
lines changed

src/Type/TypeCombinator.php

+37-3
Original file line numberDiff line numberDiff line change
@@ -780,8 +780,10 @@ private static function optimizeConstantArrays(array $types): array
780780
}
781781

782782
$results = [];
783+
$eachIsOversized = true;
783784
foreach ($types as $type) {
784-
$results[] = TypeTraverser::map($type, static function (Type $type, callable $traverse): Type {
785+
$isOversized = false;
786+
$result = TypeTraverser::map($type, static function (Type $type, callable $traverse) use (&$isOversized): Type {
785787
if (!$type instanceof ConstantArrayType) {
786788
return $traverse($type);
787789
}
@@ -790,6 +792,8 @@ private static function optimizeConstantArrays(array $types): array
790792
return $type;
791793
}
792794

795+
$isOversized = true;
796+
793797
$isList = true;
794798
$valueTypes = [];
795799
$keyTypes = [];
@@ -808,8 +812,8 @@ private static function optimizeConstantArrays(array $types): array
808812
$keyTypes[$generalizedKeyType->describe(VerbosityLevel::precise())] = $generalizedKeyType;
809813

810814
$innerValueType = $type->getValueTypes()[$i];
811-
$generalizedValueType = TypeTraverser::map($innerValueType, static function (Type $type, callable $innerTraverse) use ($traverse): Type {
812-
if ($type instanceof ArrayType) {
815+
$generalizedValueType = TypeTraverser::map($innerValueType, static function (Type $type) use ($traverse): Type {
816+
if ($type instanceof ArrayType || $type instanceof ConstantArrayType) {
813817
return TypeCombinator::intersect($type, new OversizedArrayType());
814818
}
815819

@@ -828,6 +832,36 @@ private static function optimizeConstantArrays(array $types): array
828832

829833
return TypeCombinator::intersect($arrayType, new NonEmptyArrayType(), new OversizedArrayType());
830834
});
835+
836+
if (!$isOversized) {
837+
$eachIsOversized = false;
838+
}
839+
840+
$results[] = $result;
841+
}
842+
843+
if ($eachIsOversized) {
844+
$eachIsList = true;
845+
$keyTypes = [];
846+
$valueTypes = [];
847+
foreach ($results as $result) {
848+
$keyTypes[] = $result->getIterableKeyType();
849+
$valueTypes[] = $result->getLastIterableValueType();
850+
if ($result->isList()->yes()) {
851+
continue;
852+
}
853+
$eachIsList = false;
854+
}
855+
856+
$keyType = self::union(...array_values($keyTypes));
857+
$valueType = self::union(...array_values($valueTypes));
858+
859+
$arrayType = new ArrayType($keyType, $valueType);
860+
if ($eachIsList) {
861+
$arrayType = self::intersect($arrayType, new AccessoryArrayListType());
862+
}
863+
864+
return [self::intersect($arrayType, new NonEmptyArrayType(), new OversizedArrayType())];
831865
}
832866

833867
return $results;

0 commit comments

Comments
 (0)