Skip to content

Commit ea3d4b6

Browse files
committed
in ConstantArrayTypeBuilder
1 parent a2646e6 commit ea3d4b6

File tree

2 files changed

+35
-23
lines changed

2 files changed

+35
-23
lines changed

src/Type/Constant/ConstantArrayType.php

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@
2929
use PHPStan\Type\Accessory\NonEmptyArrayType;
3030
use PHPStan\Type\ArrayType;
3131
use PHPStan\Type\BooleanType;
32-
use PHPStan\Type\CallableType;
33-
use PHPStan\Type\ClosureType;
3432
use PHPStan\Type\CompoundType;
3533
use PHPStan\Type\ConstantScalarType;
3634
use PHPStan\Type\ErrorType;
@@ -169,26 +167,7 @@ public function getIterableValueType(): Type
169167
return $this->iterableValueType;
170168
}
171169

172-
$count = count($this->valueTypes);
173-
if ($count === 0) {
174-
return $this->iterableValueType = new NeverType(true);
175-
}
176-
177-
if ($count > 16) {
178-
$onlyClosureValues = true;
179-
foreach ($this->valueTypes as $valueType) {
180-
if (!$valueType instanceof ClosureType) {
181-
$onlyClosureValues = false;
182-
break;
183-
}
184-
}
185-
186-
if ($onlyClosureValues) {
187-
return $this->iterableValueType = new CallableType();
188-
}
189-
}
190-
191-
return $this->iterableValueType = TypeCombinator::union(...$this->valueTypes);
170+
return $this->iterableValueType = count($this->valueTypes) > 0 ? TypeCombinator::union(...$this->valueTypes) : new NeverType(true);
192171
}
193172

194173
public function getKeyType(): Type

src/Type/Constant/ConstantArrayTypeBuilder.php

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
use PHPStan\Type\Accessory\NonEmptyArrayType;
99
use PHPStan\Type\Accessory\OversizedArrayType;
1010
use PHPStan\Type\ArrayType;
11+
use PHPStan\Type\CallableType;
12+
use PHPStan\Type\ClosureType;
1113
use PHPStan\Type\IntersectionType;
1214
use PHPStan\Type\Type;
1315
use PHPStan\Type\TypeCombinator;
@@ -29,9 +31,12 @@ final class ConstantArrayTypeBuilder
2931
{
3032

3133
public const ARRAY_COUNT_LIMIT = 256;
34+
private const ARRAY_CLOSURES_COUNT_LIMIT = 16;
3235

3336
private bool $degradeToGeneralArray = false;
3437

38+
private bool $degradeClosures = false;
39+
3540
private bool $oversized = false;
3641

3742
/**
@@ -79,6 +84,23 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $opt
7984
}
8085

8186
if (!$this->degradeToGeneralArray) {
87+
if ($valueType instanceof ClosureType) {
88+
$numClosures = 1;
89+
foreach ($this->valueTypes as $innerType) {
90+
if (!($innerType instanceof ClosureType)) {
91+
continue;
92+
}
93+
94+
$numClosures++;
95+
}
96+
97+
if ($numClosures >= self::ARRAY_CLOSURES_COUNT_LIMIT) {
98+
$this->degradeClosures = true;
99+
$this->degradeToGeneralArray = true;
100+
$this->oversized = true;
101+
}
102+
}
103+
82104
if ($offsetType === null) {
83105
$newAutoIndexes = $optional ? $this->nextAutoIndexes : [];
84106
$hasOptional = false;
@@ -291,9 +313,20 @@ public function getArray(): Type
291313
return new ConstantArrayType($keyTypes, $this->valueTypes, $this->nextAutoIndexes, $this->optionalKeys, $this->isList);
292314
}
293315

316+
$itemTypes = [];
317+
foreach ($this->valueTypes as $valueType) {
318+
if ($this->degradeClosures && $valueType instanceof ClosureType) {
319+
continue;
320+
}
321+
$itemTypes[] = $valueType;
322+
}
323+
if ($this->degradeClosures) {
324+
$itemTypes[] = new CallableType();
325+
}
326+
294327
$array = new ArrayType(
295328
TypeCombinator::union(...$this->keyTypes),
296-
TypeCombinator::union(...$this->valueTypes),
329+
TypeCombinator::union(...$itemTypes),
297330
);
298331

299332
$types = [];

0 commit comments

Comments
 (0)