12
12
use PHPStan \Rules \RuleLevelHelper ;
13
13
use PHPStan \Type \BenevolentUnionType ;
14
14
use PHPStan \Type \ErrorType ;
15
+ use PHPStan \Type \MixedType ;
16
+ use PHPStan \Type \NeverType ;
15
17
use PHPStan \Type \Type ;
18
+ use PHPStan \Type \TypeCombinator ;
16
19
use PHPStan \Type \TypeUtils ;
17
20
use PHPStan \Type \VerbosityLevel ;
18
21
use function count ;
@@ -44,11 +47,21 @@ public function check(
44
47
Type $ dimType ,
45
48
): array
46
49
{
50
+ if ($ dimType instanceof MixedType) {
51
+ $ dimToCheck = $ dimType ;
52
+ } else {
53
+ // Non allowed array keys are already reported by InvalidKeyInArrayItemRule
54
+ $ dimToCheck = TypeCombinator::intersect ($ dimType , AllowedArrayKeysTypes::getType ());
55
+ if ($ dimToCheck instanceof NeverType) {
56
+ return [];
57
+ }
58
+ }
59
+
47
60
$ typeResult = $ this ->ruleLevelHelper ->findTypeToCheck (
48
61
$ scope ,
49
62
NullsafeOperatorHelper::getNullsafeShortcircuitedExprRespectingScope ($ scope , $ var ),
50
63
$ unknownClassPattern ,
51
- static fn (Type $ type ): bool => $ type ->hasOffsetValueType ($ dimType )->yes (),
64
+ static fn (Type $ type ): bool => $ type ->hasOffsetValueType ($ dimToCheck )->yes (),
52
65
);
53
66
$ type = $ typeResult ->getType ();
54
67
if ($ type instanceof ErrorType) {
@@ -59,7 +72,7 @@ public function check(
59
72
return [];
60
73
}
61
74
62
- if ($ type ->hasOffsetValueType ($ dimType )->no ()) {
75
+ if ($ type ->hasOffsetValueType ($ dimToCheck )->no ()) {
63
76
return [
64
77
RuleErrorBuilder::message (sprintf ('Offset %s does not exist on %s. ' , $ dimType ->describe (count ($ dimType ->getConstantStrings ()) > 0 ? VerbosityLevel::precise () : VerbosityLevel::value ()), $ type ->describe (VerbosityLevel::value ())))
65
78
->identifier ('offsetAccess.notFound ' )
@@ -81,23 +94,23 @@ public function check(
81
94
$ this ->reportPossiblyNonexistentGeneralArrayOffset
82
95
&& $ innerType ->isArray ()->yes ()
83
96
&& !$ innerType ->isConstantArray ()->yes ()
84
- && !$ innerType ->hasOffsetValueType ($ dimType )->yes ()
97
+ && !$ innerType ->hasOffsetValueType ($ dimToCheck )->yes ()
85
98
) {
86
99
$ report = true ;
87
100
break ;
88
101
}
89
102
if (
90
103
$ this ->reportPossiblyNonexistentConstantArrayOffset
91
104
&& $ innerType ->isConstantArray ()->yes ()
92
- && !$ innerType ->hasOffsetValueType ($ dimType )->yes ()
105
+ && !$ innerType ->hasOffsetValueType ($ dimToCheck )->yes ()
93
106
) {
94
107
$ report = true ;
95
108
break ;
96
109
}
97
- if ($ dimType instanceof BenevolentUnionType) {
98
- $ flattenedInnerTypes = [$ dimType ];
110
+ if ($ dimToCheck instanceof BenevolentUnionType) {
111
+ $ flattenedInnerTypes = [$ dimToCheck ];
99
112
} else {
100
- $ flattenedInnerTypes = TypeUtils::flattenTypes ($ dimType );
113
+ $ flattenedInnerTypes = TypeUtils::flattenTypes ($ dimToCheck );
101
114
}
102
115
foreach ($ flattenedInnerTypes as $ innerDimType ) {
103
116
if (
0 commit comments