1212use PHPStan \Rules \RuleLevelHelper ;
1313use PHPStan \Type \BenevolentUnionType ;
1414use PHPStan \Type \ErrorType ;
15+ use PHPStan \Type \MixedType ;
16+ use PHPStan \Type \NeverType ;
1517use PHPStan \Type \Type ;
18+ use PHPStan \Type \TypeCombinator ;
1619use PHPStan \Type \TypeUtils ;
1720use PHPStan \Type \VerbosityLevel ;
1821use function count ;
@@ -44,11 +47,21 @@ public function check(
4447 Type $ dimType ,
4548 ): array
4649 {
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+
4760 $ typeResult = $ this ->ruleLevelHelper ->findTypeToCheck (
4861 $ scope ,
4962 NullsafeOperatorHelper::getNullsafeShortcircuitedExprRespectingScope ($ scope , $ var ),
5063 $ unknownClassPattern ,
51- static fn (Type $ type ): bool => $ type ->hasOffsetValueType ($ dimType )->yes (),
64+ static fn (Type $ type ): bool => $ type ->hasOffsetValueType ($ dimToCheck )->yes (),
5265 );
5366 $ type = $ typeResult ->getType ();
5467 if ($ type instanceof ErrorType) {
@@ -59,7 +72,7 @@ public function check(
5972 return [];
6073 }
6174
62- if ($ type ->hasOffsetValueType ($ dimType )->no ()) {
75+ if ($ type ->hasOffsetValueType ($ dimToCheck )->no ()) {
6376 return [
6477 RuleErrorBuilder::message (sprintf ('Offset %s does not exist on %s. ' , $ dimType ->describe (count ($ dimType ->getConstantStrings ()) > 0 ? VerbosityLevel::precise () : VerbosityLevel::value ()), $ type ->describe (VerbosityLevel::value ())))
6578 ->identifier ('offsetAccess.notFound ' )
@@ -81,23 +94,23 @@ public function check(
8194 $ this ->reportPossiblyNonexistentGeneralArrayOffset
8295 && $ innerType ->isArray ()->yes ()
8396 && !$ innerType ->isConstantArray ()->yes ()
84- && !$ innerType ->hasOffsetValueType ($ dimType )->yes ()
97+ && !$ innerType ->hasOffsetValueType ($ dimToCheck )->yes ()
8598 ) {
8699 $ report = true ;
87100 break ;
88101 }
89102 if (
90103 $ this ->reportPossiblyNonexistentConstantArrayOffset
91104 && $ innerType ->isConstantArray ()->yes ()
92- && !$ innerType ->hasOffsetValueType ($ dimType )->yes ()
105+ && !$ innerType ->hasOffsetValueType ($ dimToCheck )->yes ()
93106 ) {
94107 $ report = true ;
95108 break ;
96109 }
97- if ($ dimType instanceof BenevolentUnionType) {
98- $ flattenedInnerTypes = [$ dimType ];
110+ if ($ dimToCheck instanceof BenevolentUnionType) {
111+ $ flattenedInnerTypes = [$ dimToCheck ];
99112 } else {
100- $ flattenedInnerTypes = TypeUtils::flattenTypes ($ dimType );
113+ $ flattenedInnerTypes = TypeUtils::flattenTypes ($ dimToCheck );
101114 }
102115 foreach ($ flattenedInnerTypes as $ innerDimType ) {
103116 if (
0 commit comments