We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
2 parents e8d1dee + 9e4186e commit 3e29782Copy full SHA for 3e29782
4 files changed
src/Type/Constant/ConstantArrayType.php
@@ -61,6 +61,7 @@
61
use function count;
62
use function implode;
63
use function in_array;
64
+use function is_int;
65
use function is_string;
66
use function min;
67
use function pow;
@@ -1848,16 +1849,31 @@ public function makeOffsetRequired(Type $offsetType): self
1848
1849
{
1850
$offsetType = $offsetType->toArrayKey();
1851
$optionalKeys = $this->optionalKeys;
1852
+ $isList = $this->isList->yes();
1853
foreach ($this->keyTypes as $i => $keyType) {
1854
if (!$keyType->equals($offsetType)) {
1855
continue;
1856
}
1857
1858
+ $keyValue = $keyType->getValue();
1859
foreach ($optionalKeys as $j => $key) {
- if ($i === $key) {
- unset($optionalKeys[$j]);
- return new self($this->keyTypes, $this->valueTypes, $this->nextAutoIndexes, array_values($optionalKeys), $this->isList);
1860
+ if (
1861
+ $i !== $key
1862
+ && (
1863
+ !$isList
1864
+ || !is_int($keyValue)
1865
+ || !is_int($this->keyTypes[$key]->getValue())
1866
+ || $this->keyTypes[$key]->getValue() >= $keyValue
1867
+ )
1868
+ ) {
1869
+ continue;
1870
1871
+
1872
+ unset($optionalKeys[$j]);
1873
+ }
1874
1875
+ if (count($this->optionalKeys) !== count($optionalKeys)) {
1876
+ return new self($this->keyTypes, $this->valueTypes, $this->nextAutoIndexes, array_values($optionalKeys), $this->isList);
1877
1878
1879
break;
tests/PHPStan/Analyser/nsrt/bug-14177.php
@@ -12,7 +12,7 @@ class HelloWorld
12
public function testList(array $b): void
13
14
if (array_key_exists(3, $b)) {
15
- assertType('list{0: string, 1: string, 2?: string, 3: string}', $b);
+ assertType('array{string, string, string, string}', $b);
16
} else {
17
assertType('array{0: string, 1: string, 2?: string}', $b);
18
@@ -208,10 +208,10 @@ public function testFoo($l): void
208
209
if (array_key_exists(2, $l, true)) {
210
assertType('true', array_is_list($l));
211
- assertType('list{0?: string, 1?: string, 2: string}', $l);
+ assertType('array{string, string, string}', $l);
212
if (array_key_exists(1, $l, true)) {
213
214
- assertType('list{0?: string, 1: string, 2: string}', $l);
215
216
217
assertType('*NEVER*', $l);
tests/PHPStan/Rules/Variables/IssetRuleTest.php
@@ -499,6 +499,22 @@ public function testPr4374(): void
499
]);
500
501
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
518
public function testBug10640(): void
519
520
$this->treatPhpDocTypesAsCertain = true;
tests/PHPStan/Rules/Variables/data/isset-constant-array.php
@@ -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
+ if (isset($list[3])) {
+ return isset($list[2]); // offset 3 implies offset 2;
+ if (isset($list[4])) {
+ return isset($list[3]); // offset 4 implies offset 3;
19
20
+ return false;
21
22
+}
0 commit comments