Skip to content

Commit bd44528

Browse files
schlndhondrejmirtes
authored andcommitted
skip param castable to X on non-arrays
Fixes bug 12146
1 parent 7070346 commit bd44528

6 files changed

+106
-7
lines changed

src/Rules/ParameterCastableToStringCheck.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,13 @@ public function checkParameter(
3636
$scope,
3737
$parameter->value,
3838
'',
39-
static fn (Type $type): bool => !$castFn($type->getIterableValueType()) instanceof ErrorType,
39+
static fn (Type $type): bool => $type->isArray()->yes() && !$castFn($type->getIterableValueType()) instanceof ErrorType,
4040
);
4141

42-
if ($typeResult->getType() instanceof ErrorType
43-
|| !$castFn($typeResult->getType()->getIterableValueType()) instanceof ErrorType) {
42+
if (
43+
! $typeResult->getType()->isArray()->yes()
44+
|| !$castFn($typeResult->getType()->getIterableValueType()) instanceof ErrorType
45+
) {
4446
return null;
4547
}
4648

tests/PHPStan/Rules/Functions/ImplodeParameterCastableToStringRuleTest.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class ImplodeParameterCastableToStringRuleTest extends RuleTestCase
1717
protected function getRule(): Rule
1818
{
1919
$broker = $this->createReflectionProvider();
20-
return new ImplodeParameterCastableToStringRule($broker, new ParameterCastableToStringCheck(new RuleLevelHelper($broker, true, false, true, false, false, false)));
20+
return new ImplodeParameterCastableToStringRule($broker, new ParameterCastableToStringCheck(new RuleLevelHelper($broker, true, false, true, true, true, false)));
2121
}
2222

2323
public function testNamedArguments(): void
@@ -100,4 +100,14 @@ public function testBug8467a(): void
100100
$this->analyse([__DIR__ . '/../Arrays/data/bug-8467a.php'], []);
101101
}
102102

103+
public function testBug12146(): void
104+
{
105+
$this->analyse([__DIR__ . '/data/bug-12146.php'], [
106+
[
107+
'Parameter #2 $array of function implode expects array<string>, array<int|stdClass> given.',
108+
28,
109+
],
110+
]);
111+
}
112+
103113
}

tests/PHPStan/Rules/Functions/ParameterCastableToNumberRuleTest.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class ParameterCastableToNumberRuleTest extends RuleTestCase
1919
protected function getRule(): Rule
2020
{
2121
$broker = $this->createReflectionProvider();
22-
return new ParameterCastableToNumberRule($broker, new ParameterCastableToStringCheck(new RuleLevelHelper($broker, true, false, true, false, false, false)));
22+
return new ParameterCastableToNumberRule($broker, new ParameterCastableToStringCheck(new RuleLevelHelper($broker, true, false, true, true, true, false)));
2323
}
2424

2525
public function testRule(): void
@@ -130,6 +130,20 @@ public function testBug11883(): void
130130
]);
131131
}
132132

133+
public function testBug12146(): void
134+
{
135+
$this->analyse([__DIR__ . '/data/bug-12146.php'], $this->hackPhp74ErrorMessages([
136+
[
137+
'Parameter #1 $array of function array_sum expects an array of values castable to number, array<int|stdClass> given.',
138+
16,
139+
],
140+
[
141+
'Parameter #1 $array of function array_product expects an array of values castable to number, array<int|stdClass> given.',
142+
22,
143+
],
144+
]));
145+
}
146+
133147
/**
134148
* @param list<array{0: string, 1: int, 2?: string|null}> $errors
135149
* @return list<array{0: string, 1: int, 2?: string|null}>

tests/PHPStan/Rules/Functions/ParameterCastableToStringRuleTest.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class ParameterCastableToStringRuleTest extends RuleTestCase
1919
protected function getRule(): Rule
2020
{
2121
$broker = $this->createReflectionProvider();
22-
return new ParameterCastableToStringRule($broker, new ParameterCastableToStringCheck(new RuleLevelHelper($broker, true, false, true, false, false, false)));
22+
return new ParameterCastableToStringRule($broker, new ParameterCastableToStringCheck(new RuleLevelHelper($broker, true, false, true, true, true, false)));
2323
}
2424

2525
public function testRule(): void
@@ -196,6 +196,20 @@ public function testBug11141(): void
196196
]);
197197
}
198198

199+
public function testBug12146(): void
200+
{
201+
$this->analyse([__DIR__ . '/data/bug-12146.php'], $this->hackParameterNames([
202+
[
203+
'Parameter #1 $array of function array_intersect expects an array of values castable to string, array<int|stdClass> given.',
204+
34,
205+
],
206+
[
207+
'Parameter #1 $keys of function array_fill_keys expects an array of values castable to string, array<int|stdClass> given.',
208+
40,
209+
],
210+
]));
211+
}
212+
199213
/**
200214
* @param list<array{0: string, 1: int, 2?: string|null}> $errors
201215
* @return list<array{0: string, 1: int, 2?: string|null}>

tests/PHPStan/Rules/Functions/SortParameterCastableToStringRuleTest.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class SortParameterCastableToStringRuleTest extends RuleTestCase
1919
protected function getRule(): Rule
2020
{
2121
$broker = $this->createReflectionProvider();
22-
return new SortParameterCastableToStringRule($broker, new ParameterCastableToStringCheck(new RuleLevelHelper($broker, true, false, true, false, false, false)));
22+
return new SortParameterCastableToStringRule($broker, new ParameterCastableToStringCheck(new RuleLevelHelper($broker, true, false, true, true, true, false)));
2323
}
2424

2525
public function testRule(): void
@@ -145,6 +145,16 @@ public function testBug11167(): void
145145
$this->analyse([__DIR__ . '/data/bug-11167.php'], []);
146146
}
147147

148+
public function testBug12146(): void
149+
{
150+
$this->analyse([__DIR__ . '/data/bug-12146.php'], $this->hackParameterNames([
151+
[
152+
'Parameter #1 $array of function array_unique expects an array of values castable to string, array<int|stdClass> given.',
153+
46,
154+
],
155+
]));
156+
}
157+
148158
/**
149159
* @param list<array{0: string, 1: int, 2?: string|null}> $errors
150160
* @return list<array{0: string, 1: int, 2?: string|null}>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug12146;
4+
5+
/**
6+
* @param mixed $mixed invalid, but don't report because it's reported by CallToFunctionParametersRule
7+
* @param array<int>|array<float> $validArrayUnion valid
8+
* @param array<int>|array<\stdClass> $invalidArrayUnion invalid, report
9+
* @param ?array<\stdClass> $nullableInvalidArray invalid, but don't report because it's reported by CallToFunctionParametersRule
10+
* @param array<\stdClass>|\SplFixedArray<int> $arrayOrSplArray invalid, but don't report because it's reported by CallToFunctionParametersRule
11+
* @return void
12+
*/
13+
function foo($mixed, $validArrayUnion, $invalidArrayUnion, $nullableInvalidArray, $arrayOrSplArray) {
14+
var_dump(array_sum($mixed));
15+
var_dump(array_sum($validArrayUnion));
16+
var_dump(array_sum($invalidArrayUnion));
17+
var_dump(array_sum($nullableInvalidArray));
18+
var_dump(array_sum($arrayOrSplArray));
19+
20+
var_dump(array_product($mixed));
21+
var_dump(array_product($validArrayUnion));
22+
var_dump(array_product($invalidArrayUnion));
23+
var_dump(array_product($nullableInvalidArray));
24+
var_dump(array_product($arrayOrSplArray));
25+
26+
var_dump(implode(',', $mixed));
27+
var_dump(implode(',', $validArrayUnion));
28+
var_dump(implode(',', $invalidArrayUnion));
29+
var_dump(implode(',', $nullableInvalidArray));
30+
var_dump(implode(',', $arrayOrSplArray));
31+
32+
var_dump(array_intersect($mixed, [5]));
33+
var_dump(array_intersect($validArrayUnion, [5]));
34+
var_dump(array_intersect($invalidArrayUnion, [5]));
35+
var_dump(array_intersect($nullableInvalidArray, [5]));
36+
var_dump(array_intersect($arrayOrSplArray, [5]));
37+
38+
var_dump(array_fill_keys($mixed, 1));
39+
var_dump(array_fill_keys($validArrayUnion, 1));
40+
var_dump(array_fill_keys($invalidArrayUnion, 1));
41+
var_dump(array_fill_keys($nullableInvalidArray, 1));
42+
var_dump(array_fill_keys($arrayOrSplArray, 1));
43+
44+
var_dump(array_unique($mixed));
45+
var_dump(array_unique($validArrayUnion));
46+
var_dump(array_unique($invalidArrayUnion));
47+
var_dump(array_unique($nullableInvalidArray));
48+
var_dump(array_unique($arrayOrSplArray));
49+
}

0 commit comments

Comments
 (0)