Skip to content

Commit

Permalink
Make optimization a bit smarter
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Sep 3, 2022
1 parent 519059e commit ec92402
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 11 deletions.
19 changes: 18 additions & 1 deletion src/Type/Constant/ConstantArrayType.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use PHPStan\Reflection\TrivialParametersAcceptor;
use PHPStan\ShouldNotHappenException;
use PHPStan\TrinaryLogic;
use PHPStan\Type\Accessory\HasOffsetValueType;
use PHPStan\Type\Accessory\NonEmptyArrayType;
use PHPStan\Type\ArrayType;
use PHPStan\Type\BooleanType;
Expand Down Expand Up @@ -952,7 +953,23 @@ public function generalize(GeneralizePrecision $precision): Type
$this->getItemType()->generalize($precision),
);

if (count($this->keyTypes) > count($this->optionalKeys)) {
$keyTypesCount = count($this->keyTypes);
$optionalKeysCount = count($this->optionalKeys);

if ($precision->isMoreSpecific() && ($keyTypesCount - $optionalKeysCount) < 32) {
$accessoryTypes = [];
foreach ($this->keyTypes as $i => $keyType) {
if ($this->isOptionalKey($i)) {
continue;
}

$accessoryTypes[] = new HasOffsetValueType($keyType, $this->valueTypes[$i]);
}

return TypeCombinator::intersect($arrayType, ...$accessoryTypes);
}

if ($keyTypesCount > $optionalKeysCount) {
return TypeCombinator::intersect($arrayType, new NonEmptyArrayType());
}

Expand Down
22 changes: 13 additions & 9 deletions src/Type/TypeCombinator.php
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,7 @@ private static function processArrayTypes(array $arrayTypes, array $accessoryTyp

$keyTypesForGeneralArray = [];
$valueTypesForGeneralArray = [];
$generalArrayOccurred = self::shouldDegradeConstantArrays($arrayTypes);
$generalArrayOccurred = false;
$constantKeyTypesNumbered = [];

/** @var int|float $nextConstantKeyTypeIndex */
Expand Down Expand Up @@ -638,25 +638,29 @@ private static function processArrayTypes(array $arrayTypes, array $accessoryTyp
];
}

$reducedArrayTypes = self::reduceArrays($arrayTypes);

return array_map(
static fn (Type $arrayType) => self::intersect($arrayType, ...$accessoryTypes),
self::reduceArrays($arrayTypes),
self::optimizeConstantArrays($reducedArrayTypes),
);
}

/**
* @param ArrayType[] $arrayTypes
* @param Type[] $types
* @return Type[]
*/
private static function shouldDegradeConstantArrays(array $arrayTypes): bool
private static function optimizeConstantArrays(array $types): array
{
$results = [];
$constantArrayValuesCount = 0;
foreach ($arrayTypes as $arrayType) {
TypeTraverser::map($arrayType, static function (Type $type, callable $traverse) use (&$constantArrayValuesCount): Type {
foreach ($types as $type) {
$results[] = TypeTraverser::map($type, static function (Type $type, callable $traverse) use (&$constantArrayValuesCount): Type {
if ($type instanceof ConstantArrayType) {
$constantArrayValuesCount += count($type->getValueTypes());
if ($constantArrayValuesCount > ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT) {
return $type;
return $type->generalize(GeneralizePrecision::moreSpecific());
}
$constantArrayValuesCount += count($type->getValueTypes());

return $traverse($type);
}
Expand All @@ -669,7 +673,7 @@ private static function shouldDegradeConstantArrays(array $arrayTypes): bool
});
}

return $constantArrayValuesCount > ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT;
return $results;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Analyser/AnalyserIntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -931,7 +931,7 @@ public function testBug7581(): void
public function testBug7903(): void
{
$errors = $this->runAnalyse(__DIR__ . '/data/bug-7903.php');
$this->assertCount(7, $errors);
$this->assertNoErrors($errors);
}

public function testBug7901(): void
Expand Down

0 comments on commit ec92402

Please sign in to comment.