Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 17beb01

Browse files
authored
Set offset on list keeps list if there's HasOffsetType for all preceeding offsets
1 parent 194ba99 commit 17beb01

File tree

2 files changed

+65
-2
lines changed

2 files changed

+65
-2
lines changed

‎src/Type/IntersectionType.php‎

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -800,8 +800,30 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $uni
800800

801801
$result = $this->intersectTypes(static fn (Type $type): Type => $type->setOffsetValueType($offsetType, $valueType, $unionValues));
802802

803-
if ($offsetType !== null && $this->isList()->yes() && $this->isIterableAtLeastOnce()->yes() && (new ConstantIntegerType(1))->isSuperTypeOf($offsetType)->yes()) {
804-
$result = TypeCombinator::intersect($result, new AccessoryArrayListType());
803+
if (
804+
$offsetType !== null
805+
&& $this->isList()->yes()
806+
&& !$result->isList()->yes()
807+
) {
808+
if ($this->isIterableAtLeastOnce()->yes() && (new ConstantIntegerType(1))->isSuperTypeOf($offsetType)->yes()) {
809+
$result = TypeCombinator::intersect($result, new AccessoryArrayListType());
810+
} else {
811+
foreach ($this->types as $type) {
812+
if (!$type instanceof HasOffsetValueType && !$type instanceof HasOffsetType) {
813+
continue;
814+
}
815+
816+
foreach ($type->getOffsetType()->getConstantScalarValues() as $constantScalarValue) {
817+
if (!is_int($constantScalarValue)) {
818+
continue;
819+
}
820+
if (IntegerRangeType::fromInterval(0, $constantScalarValue + 1)->isSuperTypeOf($offsetType)->yes()) {
821+
$result = TypeCombinator::intersect($result, new AccessoryArrayListType());
822+
break 2;
823+
}
824+
}
825+
}
826+
}
805827
}
806828

807829
return $result;

‎tests/PHPStan/Analyser/nsrt/list-type.php‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,4 +128,45 @@ public function testSetOffsetExplicitlyWithGap(array $list): void
128128
assertType('non-empty-array<int<0, max>, int>&hasOffsetValue(0, 17)&hasOffsetValue(2, 21)', $list);
129129
}
130130

131+
/** @param list<int> $list */
132+
function testAppendImmediatelyAfterLastElement(array $list): void
133+
{
134+
assertType('list<int>', $list);
135+
$list[0] = 17;
136+
assertType('non-empty-list<int>&hasOffsetValue(0, 17)', $list);
137+
$list[1] = 19;
138+
assertType('non-empty-list<int>&hasOffsetValue(0, 17)&hasOffsetValue(1, 19)', $list);
139+
$list[2] = 21;
140+
assertType('non-empty-list<int>&hasOffsetValue(0, 17)&hasOffsetValue(1, 19)&hasOffsetValue(2, 21)', $list);
141+
$list[3] = 21;
142+
assertType('non-empty-list<int>&hasOffsetValue(0, 17)&hasOffsetValue(1, 19)&hasOffsetValue(2, 21)&hasOffsetValue(3, 21)', $list);
143+
144+
// hole in the list -> turns it into a array
145+
146+
$list[5] = 21;
147+
assertType('non-empty-array<int<0, max>, int>&hasOffsetValue(0, 17)&hasOffsetValue(1, 19)&hasOffsetValue(2, 21)&hasOffsetValue(3, 21)&hasOffsetValue(5, 21)', $list);
148+
}
149+
150+
151+
/** @param list<int> $list */
152+
function testKeepListAfterLast(array $list): void
153+
{
154+
if (isset($list[5])) {
155+
assertType('non-empty-list<int>&hasOffsetValue(5, int)', $list);
156+
$list[6] = 21;
157+
assertType('non-empty-list<int>&hasOffsetValue(5, int)&hasOffsetValue(6, 21)', $list);
158+
}
159+
assertType('list<int>', $list);
160+
}
161+
162+
/** @param list<int> $list */
163+
function testKeepListAfterLastArrayKey(array $list): void
164+
{
165+
if (array_key_exists(5, $list) && is_int($list[5])) {
166+
assertType('non-empty-list<int>&hasOffsetValue(5, int)', $list);
167+
$list[6] = 21;
168+
assertType('non-empty-list<int>&hasOffsetValue(5, int)&hasOffsetValue(6, 21)', $list);
169+
}
170+
assertType('list<int>', $list);
171+
}
131172
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /