Skip to content

Commit

Permalink
Optimization of huge unions of oversized arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Oct 26, 2024
1 parent c04555b commit 4dfbe16
Showing 1 changed file with 37 additions and 3 deletions.
40 changes: 37 additions & 3 deletions src/Type/TypeCombinator.php
Original file line number Diff line number Diff line change
Expand Up @@ -780,8 +780,10 @@ private static function optimizeConstantArrays(array $types): array
}

$results = [];
$eachIsOversized = true;
foreach ($types as $type) {
$results[] = TypeTraverser::map($type, static function (Type $type, callable $traverse): Type {
$isOversized = false;
$result = TypeTraverser::map($type, static function (Type $type, callable $traverse) use (&$isOversized): Type {
if (!$type instanceof ConstantArrayType) {
return $traverse($type);
}
Expand All @@ -790,6 +792,8 @@ private static function optimizeConstantArrays(array $types): array
return $type;
}

$isOversized = true;

$isList = true;
$valueTypes = [];
$keyTypes = [];
Expand All @@ -808,8 +812,8 @@ private static function optimizeConstantArrays(array $types): array
$keyTypes[$generalizedKeyType->describe(VerbosityLevel::precise())] = $generalizedKeyType;

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

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

return TypeCombinator::intersect($arrayType, new NonEmptyArrayType(), new OversizedArrayType());
});

if (!$isOversized) {
$eachIsOversized = false;
}

$results[] = $result;
}

if ($eachIsOversized) {
$eachIsList = true;
$keyTypes = [];
$valueTypes = [];
foreach ($results as $result) {
$keyTypes[] = $result->getIterableKeyType();
$valueTypes[] = $result->getLastIterableValueType();
if ($result->isList()->yes()) {
continue;
}
$eachIsList = false;
}

$keyType = self::union(...array_values($keyTypes));
$valueType = self::union(...array_values($valueTypes));

$arrayType = new ArrayType($keyType, $valueType);
if ($eachIsList) {
$arrayType = self::intersect($arrayType, new AccessoryArrayListType());
}

return [self::intersect($arrayType, new NonEmptyArrayType(), new OversizedArrayType())];
}

return $results;
Expand Down

0 comments on commit 4dfbe16

Please sign in to comment.