Skip to content

Commit c97b61d

Browse files
WIP
1 parent 65797b9 commit c97b61d

File tree

4 files changed

+54
-3
lines changed

4 files changed

+54
-3
lines changed

src/Type/Constant/ConstantArrayType.php

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1840,18 +1840,31 @@ public function makeOffsetRequired(Type $offsetType): self
18401840
{
18411841
$offsetType = $offsetType->toArrayKey();
18421842
$optionalKeys = $this->optionalKeys;
1843+
$isList = $this->isList->yes();
18431844
foreach ($this->keyTypes as $i => $keyType) {
18441845
if (!$keyType->equals($offsetType)) {
18451846
continue;
18461847
}
18471848

1849+
$keyValue = $keyType->getValue();
18481850
foreach ($optionalKeys as $j => $key) {
1849-
if ($i === $key) {
1851+
if (
1852+
$i === $key
1853+
|| (
1854+
$isList
1855+
&& is_int($keyValue)
1856+
&& is_int($this->keyTypes[$key]->getValue())
1857+
&& $this->keyTypes[$key]->getValue() < $keyValue
1858+
)
1859+
) {
18501860
unset($optionalKeys[$j]);
1851-
return new self($this->keyTypes, $this->valueTypes, $this->nextAutoIndexes, array_values($optionalKeys), $this->isList);
18521861
}
18531862
}
18541863

1864+
if (count($this->optionalKeys) !== count($optionalKeys)) {
1865+
return new self($this->keyTypes, $this->valueTypes, $this->nextAutoIndexes, array_values($optionalKeys), $this->isList);
1866+
}
1867+
18551868
break;
18561869
}
18571870

tests/PHPStan/Analyser/nsrt/bug-14177.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class HelloWorld
1212
public function testList(array $b): void
1313
{
1414
if (array_key_exists(3, $b)) {
15-
assertType('list{0: string, 1: string, 2?: string, 3: string}', $b);
15+
assertType('array{string, string, string, string}', $b);
1616
} else {
1717
assertType('array{0: string, 1: string, 2?: string}', $b);
1818
}

tests/PHPStan/Rules/Variables/IssetRuleTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,22 @@ public function testPr4374(): void
499499
]);
500500
}
501501

502+
public function testIssetConstantArray(): void
503+
{
504+
$this->treatPhpDocTypesAsCertain = true;
505+
506+
$this->analyse([__DIR__ . '/data/isset-constant-array.php'], [
507+
[
508+
'Offset 2 on array{0: string, 1: string, 2: string, 3: string, 4?: string} in isset() always exists and is not nullable.',
509+
13,
510+
],
511+
[
512+
'Offset 3 on array{string, string, string, string, string} in isset() always exists and is not nullable.',
513+
17,
514+
],
515+
]);
516+
}
517+
502518
public function testBug10640(): void
503519
{
504520
$this->treatPhpDocTypesAsCertain = true;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace IssetConstantArray;
4+
5+
class HelloWorld
6+
{
7+
/**
8+
* @param list{0: string, 1: string, 2?: string, 3?: string, 4?: string} $list
9+
*/
10+
public function sayHello(array $list): bool
11+
{
12+
if (isset($list[3])) {
13+
return isset($list[2]); // offset 3 implies offset 2;
14+
}
15+
16+
if (isset($list[4])) {
17+
return isset($list[3]); // offset 4 implies offset 3;
18+
}
19+
20+
return false;
21+
}
22+
}

0 commit comments

Comments
 (0)