Skip to content

Commit 8386e34

Browse files
committed
Use Type->setExistingOffsetValueType() more
1 parent 032d2e7 commit 8386e34

File tree

6 files changed

+49
-14
lines changed

6 files changed

+49
-14
lines changed

src/Analyser/NodeScopeResolver.php

+10-1
Original file line numberDiff line numberDiff line change
@@ -5919,9 +5919,18 @@ private function produceArrayDimFetchAssignValueToWrite(array $dimFetchStack, ar
59195919
}
59205920
$offsetValueType = TypeCombinator::intersect($offsetValueType, TypeCombinator::union(...$types));
59215921
}
5922-
$valueToWrite = $offsetValueType->setOffsetValueType($offsetType, $valueToWrite, $i === 0);
59235922

59245923
$arrayDimFetch = $dimFetchStack[$i] ?? null;
5924+
if (
5925+
$offsetType !== null
5926+
&& $arrayDimFetch !== null
5927+
&& $scope->hasExpressionType($arrayDimFetch)->yes()
5928+
) {
5929+
$valueToWrite = $offsetValueType->setExistingOffsetValueType($offsetType, $valueToWrite);
5930+
} else {
5931+
$valueToWrite = $offsetValueType->setOffsetValueType($offsetType, $valueToWrite, $i === 0);
5932+
}
5933+
59255934
if ($arrayDimFetch === null || !$offsetValueType->isList()->yes()) {
59265935
continue;
59275936
}

src/Type/Accessory/AccessoryArrayListType.php

-7
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

+4
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

+24-3
Original file line numberDiff line numberDiff line change
@@ -356,9 +356,30 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $uni
356356

357357
public function setExistingOffsetValueType(Type $offsetType, Type $valueType): Type
358358
{
359-
return new self(
360-
$this->keyType,
361-
TypeCombinator::union($this->itemType, $valueType),
359+
if ($offsetType instanceof ConstantStringType || $offsetType instanceof ConstantIntegerType) {
360+
if ($offsetType->isSuperTypeOf($this->keyType)->yes()) {
361+
$builder = ConstantArrayTypeBuilder::createEmpty();
362+
$builder->setOffsetValueType($offsetType, $valueType);
363+
return $builder->getArray();
364+
}
365+
366+
return TypeCombinator::intersect(
367+
new self(
368+
TypeCombinator::union($this->keyType, $offsetType),
369+
TypeCombinator::union($this->itemType, $valueType),
370+
),
371+
new HasOffsetValueType($offsetType, $valueType),
372+
new NonEmptyArrayType(),
373+
);
374+
}
375+
376+
377+
return TypeCombinator::intersect(
378+
new self(
379+
$this->keyType,
380+
TypeCombinator::union($this->itemType, $valueType)
381+
),
382+
new NonEmptyArrayType(),
362383
);
363384
}
364385

src/Type/Constant/ConstantArrayType.php

+7
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
use function min;
6464
use function pow;
6565
use function range;
66+
use function ReturnTypes\containsYield;
6667
use function sort;
6768
use function sprintf;
6869
use function str_contains;
@@ -688,11 +689,17 @@ public function setExistingOffsetValueType(Type $offsetType, Type $valueType): T
688689
{
689690
$offsetType = $offsetType->toArrayKey();
690691
$builder = ConstantArrayTypeBuilder::createFromConstantArray($this);
692+
$unionValues = $offsetType instanceof UnionType && count($offsetType->getTypes()) > 1;
691693
foreach ($this->keyTypes as $keyType) {
692694
if ($offsetType->isSuperTypeOf($keyType)->no()) {
693695
continue;
694696
}
695697

698+
if ($unionValues) {
699+
$builder->setOffsetValueType($keyType, TypeCombinator::union($this->getOffsetValueType($keyType), $valueType));
700+
continue;
701+
}
702+
696703
$builder->setOffsetValueType($keyType, $valueType);
697704
}
698705

src/Type/IntersectionType.php

+4-3
Original file line numberDiff line numberDiff line change
@@ -799,9 +799,6 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $uni
799799
}
800800

801801
$result = $this->intersectTypes(static fn (Type $type): Type => $type->setOffsetValueType($offsetType, $valueType, $unionValues));
802-
if ($this->isList()->yes() && $valueType->isArray()->yes()) {
803-
$result = TypeCombinator::intersect($result, new AccessoryArrayListType());
804-
}
805802

806803
if (
807804
$offsetType !== null
@@ -829,6 +826,10 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $uni
829826
}
830827
}
831828

829+
if ($this->isList()->yes() && $this->getIterableValueType()->isArray()->yes()) {
830+
$result = TypeCombinator::intersect($result, new AccessoryArrayListType());
831+
}
832+
832833
return $result;
833834
}
834835

0 commit comments

Comments
 (0)