Skip to content

Commit 17a6158

Browse files
authored
Last value was not recognized when passing an associative array as an argument
1 parent 2d637da commit 17a6158

File tree

3 files changed

+60
-5
lines changed

3 files changed

+60
-5
lines changed

src/Rules/FunctionCallParametersCheck.php

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
use function array_key_exists;
3131
use function count;
3232
use function implode;
33+
use function in_array;
3334
use function is_int;
3435
use function is_string;
3536
use function max;
@@ -128,30 +129,32 @@ public function check(
128129
if ($arg->unpack) {
129130
$arrays = $type->getConstantArrays();
130131
if (count($arrays) > 0) {
131-
$minKeys = null;
132+
$maxKeys = null;
132133
foreach ($arrays as $array) {
133134
$countType = $array->getArraySize();
134135
if ($countType instanceof ConstantIntegerType) {
135136
$keysCount = $countType->getValue();
136137
} elseif ($countType instanceof IntegerRangeType) {
137-
$keysCount = $countType->getMin();
138+
$keysCount = $countType->getMax();
138139
if ($keysCount === null) {
139140
throw new ShouldNotHappenException();
140141
}
141142
} else {
142143
throw new ShouldNotHappenException();
143144
}
144-
if ($minKeys !== null && $keysCount >= $minKeys) {
145+
if ($maxKeys !== null && $keysCount >= $maxKeys) {
145146
continue;
146147
}
147148

148-
$minKeys = $keysCount;
149+
$maxKeys = $keysCount;
149150
}
150151

151-
for ($j = 0; $j < $minKeys; $j++) {
152+
for ($j = 0; $j < $maxKeys; $j++) {
152153
$types = [];
153154
$commonKey = null;
155+
$isOptionalKey = false;
154156
foreach ($arrays as $constantArray) {
157+
$isOptionalKey = in_array($j, $constantArray->getOptionalKeys(), true);
155158
$types[] = $constantArray->getValueTypes()[$j];
156159
$keyType = $constantArray->getKeyTypes()[$j];
157160
if ($commonKey === null) {
@@ -165,6 +168,10 @@ public function check(
165168
$keyArgumentName = $commonKey;
166169
$hasNamedArguments = true;
167170
}
171+
if ($isOptionalKey) {
172+
continue;
173+
}
174+
168175
$arguments[] = [
169176
$arg->value,
170177
TypeCombinator::union(...$types),

tests/PHPStan/Rules/Classes/InstantiationRuleTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,4 +499,9 @@ public function testBug10248(): void
499499
$this->analyse([__DIR__ . '/data/bug-10248.php'], []);
500500
}
501501

502+
public function testBug11815(): void
503+
{
504+
$this->analyse([__DIR__ . '/data/bug-11815.php'], []);
505+
}
506+
502507
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php // lint >= 8.2
2+
3+
declare(strict_types = 1);
4+
5+
class Dimensions
6+
{
7+
public function __construct(
8+
public int $width,
9+
public int $height,
10+
) {
11+
}
12+
}
13+
14+
class StoreProcessorResult
15+
{
16+
public function __construct(
17+
public string $path,
18+
public string $mimetype,
19+
public Dimensions $dimensions,
20+
public int $filesize,
21+
public true|null $identical = null,
22+
) {
23+
}
24+
}
25+
26+
/**
27+
* @return array{path: string, identical?: true}
28+
*/
29+
function getPath(): array
30+
{
31+
$data = ['path' => 'some/path'];
32+
if ((bool)rand(0, 1)) {
33+
$data['identical'] = true;
34+
}
35+
return $data;
36+
}
37+
38+
$data = getPath();
39+
$data['dimensions'] = new Dimensions(100, 100);
40+
$data['mimetype'] = 'image/png';
41+
$data['filesize'] = 123456;
42+
43+
$dto = new StoreProcessorResult(...$data);

0 commit comments

Comments
 (0)