Skip to content

Commit

Permalink
Avoid new HasOffsetValueType being intersected with oversized array
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Oct 26, 2024
1 parent 16f63b3 commit deef919
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 0 deletions.
10 changes: 10 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -1170,6 +1170,11 @@ parameters:
count: 3
path: src/Type/IntersectionType.php

-
message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#"
count: 1
path: src/Type/IntersectionType.php

-
message: "#^Doing instanceof PHPStan\\\\Type\\\\BooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isBoolean\\(\\) instead\\.$#"
count: 1
Expand All @@ -1180,6 +1185,11 @@ parameters:
count: 2
path: src/Type/IntersectionType.php

-
message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#"
count: 1
path: src/Type/IntersectionType.php

-
message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#"
count: 4
Expand Down
2 changes: 2 additions & 0 deletions src/Type/Constant/ConstantArrayTypeBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $opt

if (count($this->keyTypes) > self::ARRAY_COUNT_LIMIT) {
$this->degradeToGeneralArray = true;
$this->oversized = true;
}

return;
Expand Down Expand Up @@ -194,6 +195,7 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $opt

if (count($this->keyTypes) > self::ARRAY_COUNT_LIMIT) {
$this->degradeToGeneralArray = true;
$this->oversized = true;
}

return;
Expand Down
25 changes: 25 additions & 0 deletions src/Type/IntersectionType.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
use PHPStan\Type\Accessory\AccessoryType;
use PHPStan\Type\Accessory\NonEmptyArrayType;
use PHPStan\Type\Constant\ConstantIntegerType;
use PHPStan\Type\Constant\ConstantStringType;
use PHPStan\Type\Generic\TemplateType;
use PHPStan\Type\Generic\TemplateTypeMap;
use PHPStan\Type\Generic\TemplateTypeVariance;
Expand Down Expand Up @@ -722,6 +723,30 @@ public function getOffsetValueType(Type $offsetType): Type

public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = true): Type
{
if ($this->isOversizedArray()->yes()) {
return $this->intersectTypes(static function (Type $type) use ($offsetType, $valueType, $unionValues): Type {
// avoid new HasOffsetValueType being intersected with oversized array
if (!$type instanceof ArrayType) {
return $type->setOffsetValueType($offsetType, $valueType, $unionValues);
}

if (!$offsetType instanceof ConstantStringType && !$offsetType instanceof ConstantIntegerType) {
return $type->setOffsetValueType($offsetType, $valueType, $unionValues);
}

if (!$offsetType->isSuperTypeOf($type->getKeyType())->yes()) {
return $type->setOffsetValueType($offsetType, $valueType, $unionValues);
}

return TypeCombinator::intersect(
new ArrayType(
TypeCombinator::union($type->getKeyType(), $offsetType),
TypeCombinator::union($type->getItemType(), $valueType),
),
new NonEmptyArrayType(),
);
});
}
return $this->intersectTypes(static fn (Type $type): Type => $type->setOffsetValueType($offsetType, $valueType, $unionValues));
}

Expand Down

0 comments on commit deef919

Please sign in to comment.