Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 89ee746

Browse files
VincentLangletondrejmirtes
authored andcommitted
Fix
1 parent 4972fd9 commit 89ee746

File tree

6 files changed

+111
-44
lines changed

6 files changed

+111
-44
lines changed

‎src/Rules/Arrays/NonexistentOffsetInArrayDimFetchCheck.php‎

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
use PHPStan\Rules\RuleLevelHelper;
1313
use PHPStan\Type\BenevolentUnionType;
1414
use PHPStan\Type\ErrorType;
15+
use PHPStan\Type\NeverType;
1516
use PHPStan\Type\Type;
17+
use PHPStan\Type\TypeCombinator;
1618
use PHPStan\Type\TypeUtils;
1719
use PHPStan\Type\VerbosityLevel;
1820
use function count;
@@ -60,6 +62,14 @@ public function check(
6062
}
6163

6264
if ($type->hasOffsetValueType($dimType)->no()) {
65+
if ($type->isArray()->yes()) {
66+
$validArrayDimType = TypeCombinator::intersect(AllowedArrayKeysTypes::getType(), $dimType);
67+
if ($validArrayDimType instanceof NeverType) {
68+
// Already reported by InvalidKeyInArrayDimFetchRule
69+
return [];
70+
}
71+
}
72+
6373
return [
6474
RuleErrorBuilder::message(sprintf('Offset %s does not exist on %s.', $dimType->describe(count($dimType->getConstantStrings()) > 0 ? VerbosityLevel::precise() : VerbosityLevel::value()), $type->describe(VerbosityLevel::value())))
6575
->identifier('offsetAccess.notFound')
@@ -76,28 +86,32 @@ public function check(
7686
$flattenedTypes = TypeUtils::flattenTypes($type);
7787
}
7888

89+
$validArrayDimType = TypeCombinator::intersect(AllowedArrayKeysTypes::getType(), $dimType);
90+
7991
foreach ($flattenedTypes as $innerType) {
92+
$dimTypeToCheck = $innerType->isArray()->yes() ? $validArrayDimType : $dimType;
93+
8094
if (
8195
$this->reportPossiblyNonexistentGeneralArrayOffset
8296
&& $innerType->isArray()->yes()
8397
&& !$innerType->isConstantArray()->yes()
84-
&& !$innerType->hasOffsetValueType($dimType)->yes()
98+
&& !$innerType->hasOffsetValueType($dimTypeToCheck)->yes()
8599
) {
86100
$report = true;
87101
break;
88102
}
89103
if (
90104
$this->reportPossiblyNonexistentConstantArrayOffset
91105
&& $innerType->isConstantArray()->yes()
92-
&& !$innerType->hasOffsetValueType($dimType)->yes()
106+
&& !$innerType->hasOffsetValueType($dimTypeToCheck)->yes()
93107
) {
94108
$report = true;
95109
break;
96110
}
97-
if ($dimType instanceof BenevolentUnionType) {
98-
$flattenedInnerTypes = [$dimType];
111+
if ($dimTypeToCheck instanceof BenevolentUnionType) {
112+
$flattenedInnerTypes = [$dimTypeToCheck];
99113
} else {
100-
$flattenedInnerTypes = TypeUtils::flattenTypes($dimType);
114+
$flattenedInnerTypes = TypeUtils::flattenTypes($dimTypeToCheck);
101115
}
102116
foreach ($flattenedInnerTypes as $innerDimType) {
103117
if (

‎tests/PHPStan/Levels/data/arrayOffsetAccess-3.json‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,5 @@
33
"message": "Invalid array key type DateTimeImmutable.",
44
"line": 17,
55
"ignorable": true
6-
},
7-
{
8-
"message": "Offset DateTimeImmutable does not exist on array.",
9-
"line": 17,
10-
"ignorable": true
116
}
127
]

‎tests/PHPStan/Levels/data/arrayOffsetAccess-7.json‎

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,24 @@
11
[
2-
{
3-
"message": "Offset int|object might not exist on array.",
4-
"line": 19,
5-
"ignorable": true
6-
},
72
{
83
"message": "Possibly invalid array key type int|object.",
94
"line": 19,
105
"ignorable": true
116
},
12-
{
13-
"message": "Offset object|null might not exist on array.",
14-
"line": 20,
15-
"ignorable": true
16-
},
177
{
188
"message": "Possibly invalid array key type object|null.",
199
"line": 20,
2010
"ignorable": true
2111
},
22-
{
23-
"message": "Offset DateTimeImmutable might not exist on array|ArrayAccess.",
24-
"line": 26,
25-
"ignorable": true
26-
},
2712
{
2813
"message": "Possibly invalid array key type DateTimeImmutable.",
2914
"line": 26,
3015
"ignorable": true
3116
},
32-
{
33-
"message": "Offset int|object might not exist on array|ArrayAccess.",
34-
"line": 28,
35-
"ignorable": true
36-
},
3717
{
3818
"message": "Possibly invalid array key type int|object.",
3919
"line": 28,
4020
"ignorable": true
4121
},
42-
{
43-
"message": "Offset object|null might not exist on array|ArrayAccess.",
44-
"line": 29,
45-
"ignorable": true
46-
},
4722
{
4823
"message": "Possibly invalid array key type object|null.",
4924
"line": 29,

‎tests/PHPStan/Levels/data/stringOffsetAccess-3.json‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,5 @@
1818
"message": "Invalid array key type stdClass.",
1919
"line": 59,
2020
"ignorable": true
21-
},
22-
{
23-
"message": "Offset stdClass does not exist on array{baz: 21}|array{foo: 17, bar: 19}.",
24-
"line": 59,
25-
"ignorable": true
2621
}
2722
]

‎tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php‎

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -949,10 +949,6 @@ public function testBugObject(): void
949949
'Offset int|object does not exist on array{baz: 21}|array{foo: 17, bar: 19}.',
950950
12,
951951
],
952-
[
953-
'Offset object does not exist on array<string, int>.',
954-
21,
955-
],
956952
]);
957953
}
958954

@@ -1049,6 +1045,55 @@ public function testBug13538(): void
10491045
]);
10501046
}
10511047

1048+
public function testPR4385(): void
1049+
{
1050+
$this->reportPossiblyNonexistentGeneralArrayOffset = true;
1051+
$this->reportPossiblyNonexistentConstantArrayOffset = true;
1052+
1053+
$this->analyse([__DIR__ . '/data/pr-4385.php'], [
1054+
[
1055+
'Offset int might not exist on array<int>.',
1056+
24,
1057+
],
1058+
[
1059+
'Offset string might not exist on array<int>.',
1060+
25,
1061+
],
1062+
[
1063+
'Offset array<int>|int might not exist on array<int>.',
1064+
28,
1065+
],
1066+
[
1067+
'Offset array<int>|string might not exist on array<int>.',
1068+
29,
1069+
],
1070+
[
1071+
'Offset 0|array<int> might not exist on array<int>.',
1072+
30,
1073+
],
1074+
[
1075+
'Offset int might not exist on array{string}.',
1076+
33,
1077+
],
1078+
[
1079+
'Offset string might not exist on array{string}.',
1080+
34,
1081+
],
1082+
[
1083+
'Offset array<int>|int might not exist on array{string}.',
1084+
37,
1085+
],
1086+
[
1087+
'Offset array<int>|string might not exist on array{string}.',
1088+
38,
1089+
],
1090+
[
1091+
'Offset array<int>|int might not exist on array<int>|string.',
1092+
41,
1093+
],
1094+
]);
1095+
}
1096+
10521097
public function testBug12805(): void
10531098
{
10541099
$this->reportPossiblyNonexistentGeneralArrayOffset = true;
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace Pr4385;
4+
5+
class Foo
6+
{
7+
/**
8+
* @param array<int> $array
9+
* @param int $int
10+
* @param string $string
11+
* @param object $object
12+
* @param array{0: string} $constantArray
13+
*
14+
* @return void
15+
*/
16+
public function test($array, $int, $string, $object, $constantArray)
17+
{
18+
$arrayOrObject = rand(0, 1) ? $array : $object;
19+
$arrayOrInt = rand(0, 1) ? $array : $int;
20+
$arrayOrString = rand(0, 1) ? $array : $string;
21+
$arrayOrZero = rand(0, 1) ? $array : 0;
22+
23+
$array[$array];
24+
$array[$int];
25+
$array[$string];
26+
$array[$object]; // Reported by InvalidKeyInArrayDimFetchRule
27+
$array[$arrayOrObject]; // Reported by InvalidKeyInArrayDimFetchRule
28+
$array[$arrayOrInt];
29+
$array[$arrayOrString];
30+
$array[$arrayOrZero];
31+
32+
$constantArray[$array];
33+
$constantArray[$int];
34+
$constantArray[$string];
35+
$constantArray[$object]; // Reported by InvalidKeyInArrayDimFetchRule
36+
$constantArray[$arrayOrObject]; // Reported by InvalidKeyInArrayDimFetchRule
37+
$constantArray[$arrayOrInt];
38+
$constantArray[$arrayOrString];
39+
$constantArray[$arrayOrZero]; // Reported by InvalidKeyInArrayDimFetchRule
40+
41+
$arrayOrString[$arrayOrInt];
42+
}
43+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /