Skip to content

Commit 21178f2

Browse files
committed
Use Type->setExistingOffsetValueType() more
1 parent 3e2c32d commit 21178f2

File tree

6 files changed

+48
-14
lines changed

6 files changed

+48
-14
lines changed

src/Analyser/NodeScopeResolver.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5936,9 +5936,18 @@ private function produceArrayDimFetchAssignValueToWrite(array $dimFetchStack, ar
59365936
}
59375937
$offsetValueType = TypeCombinator::intersect($offsetValueType, TypeCombinator::union(...$types));
59385938
}
5939-
$valueToWrite = $offsetValueType->setOffsetValueType($offsetType, $valueToWrite, $i === 0);
59405939

59415940
$arrayDimFetch = $dimFetchStack[$i] ?? null;
5941+
if (
5942+
$offsetType !== null
5943+
&& $arrayDimFetch !== null
5944+
&& $scope->hasExpressionType($arrayDimFetch)->yes()
5945+
) {
5946+
$valueToWrite = $offsetValueType->setExistingOffsetValueType($offsetType, $valueToWrite);
5947+
} else {
5948+
$valueToWrite = $offsetValueType->setOffsetValueType($offsetType, $valueToWrite, $i === 0);
5949+
}
5950+
59425951
if ($arrayDimFetch === null || !$offsetValueType->isList()->yes()) {
59435952
continue;
59445953
}

src/Type/Accessory/AccessoryArrayListType.php

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -151,13 +151,6 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $uni
151151
return $this;
152152
}
153153

154-
if (
155-
$valueType->isArray()->yes()
156-
&& IntegerRangeType::fromInterval(0, null)->isSuperTypeOf($offsetType)->yes()
157-
) {
158-
return $this;
159-
}
160-
161154
return new ErrorType();
162155
}
163156

src/Type/Accessory/HasOffsetValueType.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,10 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $uni
184184

185185
public function setExistingOffsetValueType(Type $offsetType, Type $valueType): Type
186186
{
187+
if (!$offsetType->equals($this->offsetType)) {
188+
return $this;
189+
}
190+
187191
return new self($this->offsetType, $valueType);
188192
}
189193

src/Type/ArrayType.php

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -361,9 +361,30 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $uni
361361

362362
public function setExistingOffsetValueType(Type $offsetType, Type $valueType): Type
363363
{
364-
return new self(
365-
$this->keyType,
366-
TypeCombinator::union($this->itemType, $valueType),
364+
if ($offsetType instanceof ConstantStringType || $offsetType instanceof ConstantIntegerType) {
365+
if ($offsetType->isSuperTypeOf($this->keyType)->yes()) {
366+
$builder = ConstantArrayTypeBuilder::createEmpty();
367+
$builder->setOffsetValueType($offsetType, $valueType);
368+
return $builder->getArray();
369+
}
370+
371+
return TypeCombinator::intersect(
372+
new self(
373+
TypeCombinator::union($this->keyType, $offsetType),
374+
TypeCombinator::union($this->itemType, $valueType),
375+
),
376+
new HasOffsetValueType($offsetType, $valueType),
377+
new NonEmptyArrayType(),
378+
);
379+
}
380+
381+
382+
return TypeCombinator::intersect(
383+
new self(
384+
$this->keyType,
385+
TypeCombinator::union($this->itemType, $valueType)
386+
),
387+
new NonEmptyArrayType(),
367388
);
368389
}
369390

src/Type/Constant/ConstantArrayType.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,11 +695,17 @@ public function setExistingOffsetValueType(Type $offsetType, Type $valueType): T
695695
{
696696
$offsetType = $offsetType->toArrayKey();
697697
$builder = ConstantArrayTypeBuilder::createFromConstantArray($this);
698+
$unionValues = $offsetType instanceof UnionType && count($offsetType->getTypes()) > 1;
698699
foreach ($this->keyTypes as $keyType) {
699700
if ($offsetType->isSuperTypeOf($keyType)->no()) {
700701
continue;
701702
}
702703

704+
if ($unionValues) {
705+
$builder->setOffsetValueType($keyType, TypeCombinator::union($this->getOffsetValueType($keyType), $valueType));
706+
continue;
707+
}
708+
703709
$builder->setOffsetValueType($keyType, $valueType);
704710
}
705711

src/Type/IntersectionType.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -802,9 +802,6 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $uni
802802
}
803803

804804
$result = $this->intersectTypes(static fn (Type $type): Type => $type->setOffsetValueType($offsetType, $valueType, $unionValues));
805-
if ($this->isList()->yes() && $valueType->isArray()->yes()) {
806-
$result = TypeCombinator::intersect($result, new AccessoryArrayListType());
807-
}
808805

809806
if (
810807
$offsetType !== null
@@ -832,6 +829,10 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $uni
832829
}
833830
}
834831

832+
if ($this->isList()->yes() && $this->getIterableValueType()->isArray()->yes()) {
833+
$result = TypeCombinator::intersect($result, new AccessoryArrayListType());
834+
}
835+
835836
return $result;
836837
}
837838

0 commit comments

Comments
 (0)