@@ -4229,29 +4229,41 @@ public function specifyExpressionType(Expr $expr, Type $type, Type $nativeType,
42294229
42304230 $ scope = $ this ;
42314231 if ($ expr instanceof Expr \ArrayDimFetch && $ expr ->dim !== null ) {
4232- $ dimType = $ scope ->getType ($ expr ->dim )->toArrayKey ();
4233- if ($ dimType instanceof ConstantIntegerType || $ dimType instanceof ConstantStringType) {
4232+ $ dimTypes = $ scope ->getType ($ expr ->dim )->getConstantArrayKeys ();
4233+
4234+ if ($ dimTypes !== []) {
42344235 $ exprVarType = $ scope ->getType ($ expr ->var );
42354236 if (!$ exprVarType instanceof MixedType && !$ exprVarType ->isArray ()->no ()) {
4237+ $ hasOffsets = [];
4238+ $ containsInteger = false ;
4239+ foreach ($ dimTypes as $ dimType ) {
4240+ $ hasOffsets [] = new HasOffsetValueType ($ dimType , $ type );
4241+
4242+ if ($ dimType instanceof ConstantIntegerType) {
4243+ $ containsInteger = true ;
4244+ }
4245+ }
4246+
42364247 $ types = [
42374248 new ArrayType (new MixedType (), new MixedType ()),
42384249 new ObjectType (ArrayAccess::class),
42394250 new NullType (),
42404251 ];
4241- if ($ dimType instanceof ConstantIntegerType ) {
4252+ if ($ containsInteger ) {
42424253 $ types [] = new StringType ();
42434254 }
42444255
42454256 $ scope = $ scope ->specifyExpressionType (
42464257 $ expr ->var ,
42474258 TypeCombinator::intersect (
42484259 TypeCombinator::intersect ($ exprVarType , TypeCombinator::union (...$ types )),
4249- new HasOffsetValueType ( $ dimType , $ type ) ,
4260+ ... $ hasOffsets ,
42504261 ),
42514262 $ scope ->getNativeType ($ expr ->var ),
42524263 $ certainty ,
42534264 );
42544265 }
4266+
42554267 }
42564268 }
42574269
0 commit comments