Skip to content

Commit b2f0742

Browse files
WIP
1 parent a355076 commit b2f0742

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
@@ -1828,18 +1828,31 @@ public function makeOffsetRequired(Type $offsetType): self
18281828
{
18291829
$offsetType = $offsetType->toArrayKey();
18301830
$optionalKeys = $this->optionalKeys;
1831+
$isList = $this->isList->yes();
18311832
foreach ($this->keyTypes as $i => $keyType) {
18321833
if (!$keyType->equals($offsetType)) {
18331834
continue;
18341835
}
18351836

1837+
$keyValue = $keyType->getValue();
18361838
foreach ($optionalKeys as $j => $key) {
1837-
if ($i === $key) {
1839+
if (
1840+
$i === $key
1841+
|| (
1842+
$isList
1843+
&& is_int($keyValue)
1844+
&& is_int($this->keyTypes[$key]->getValue())
1845+
&& $this->keyTypes[$key]->getValue() < $keyValue
1846+
)
1847+
) {
18381848
unset($optionalKeys[$j]);
1839-
return new self($this->keyTypes, $this->valueTypes, $this->nextAutoIndexes, array_values($optionalKeys), $this->isList);
18401849
}
18411850
}
18421851

1852+
if (count($this->optionalKeys) !== count($optionalKeys)) {
1853+
return new self($this->keyTypes, $this->valueTypes, $this->nextAutoIndexes, array_values($optionalKeys), $this->isList);
1854+
}
1855+
18431856
break;
18441857
}
18451858

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)