@@ -782,6 +782,9 @@ public function getArraySize(): Type
782782
783783 public function getIterableKeyType (): Type
784784 {
785+ if ($ this ->isCallable ()->yes () && $ this ->isArray ()->yes ()) {
786+ return new UnionType ([new ConstantIntegerType (0 ), new ConstantIntegerType (1 )]);
787+ }
785788 return $ this ->intersectTypes (static fn (Type $ type ): Type => $ type ->getIterableKeyType ());
786789 }
787790
@@ -797,7 +800,17 @@ public function getLastIterableKeyType(): Type
797800
798801 public function getIterableValueType (): Type
799802 {
800- return $ this ->intersectTypes (static fn (Type $ type ): Type => $ type ->getIterableValueType ());
803+ $ result = $ this ->intersectTypes (static fn (Type $ type ): Type => $ type ->getIterableValueType ());
804+ if ($ this ->isCallable ()->yes () && $ this ->isArray ()->yes ()) {
805+ return TypeCombinator::intersect (
806+ $ result ,
807+ new UnionType ([
808+ new ObjectWithoutClassType (),
809+ new IntersectionType ([new StringType (), new AccessoryNonFalsyStringType ()]),
810+ ]),
811+ );
812+ }
813+ return $ result ;
801814 }
802815
803816 public function getFirstIterableValueType (): Type
@@ -960,17 +973,15 @@ private function doHasOffsetValueType(Type $offsetType): TrinaryLogic
960973 }
961974 }
962975
963- $ result = $ this ->intersectResults (static fn (Type $ type ): TrinaryLogic => $ type ->hasOffsetValueType ($ offsetType ));
964-
965- if (!$ result ->yes () && $ this ->isCallable ()->yes () && $ this ->isArray ()->yes ()) {
976+ if ($ this ->isCallable ()->yes () && $ this ->isArray ()->yes ()) {
966977 $ arrayKeyOffsetType = $ offsetType ->toArrayKey ();
967978 $ callableArrayOffsetType = new UnionType ([new ConstantIntegerType (0 ), new ConstantIntegerType (1 )]);
968979 if ($ callableArrayOffsetType ->isSuperTypeOf ($ arrayKeyOffsetType )->yes ()) {
969980 return TrinaryLogic::createYes ();
970981 }
971982 }
972983
973- return $ result ;
984+ return $ this -> intersectResults ( static fn ( Type $ type ): TrinaryLogic => $ type -> hasOffsetValueType ( $ offsetType )) ;
974985 }
975986
976987 public function getOffsetValueType (Type $ offsetType ): Type
@@ -991,17 +1002,14 @@ private function doGetOffsetValueType(Type $offsetType): Type
9911002
9921003 if ($ this ->isCallable ()->yes () && $ this ->isArray ()->yes ()) {
9931004 $ arrayKeyOffsetType = $ offsetType ->toArrayKey ();
994- $ callableArrayOffsetType = new UnionType ([new ConstantIntegerType (0 ), new ConstantIntegerType (1 )]);
995- if ($ callableArrayOffsetType ->isSuperTypeOf ($ arrayKeyOffsetType )->yes ()) {
996- if ((new ConstantIntegerType (0 ))->isSuperTypeOf ($ arrayKeyOffsetType )->yes ()) {
997- $ narrowedType = new UnionType ([new ClassStringType (), new ObjectWithoutClassType ()]);
998- } elseif ((new ConstantIntegerType (1 ))->isSuperTypeOf ($ arrayKeyOffsetType )->yes ()) {
999- $ narrowedType = new StringType ();
1000- } else {
1001- $ narrowedType = new UnionType ([new StringType (), new ObjectWithoutClassType ()]);
1002- }
1003- $ result = TypeCombinator::intersect ($ result , $ narrowedType );
1005+ if ((new ConstantIntegerType (0 ))->isSuperTypeOf ($ arrayKeyOffsetType )->yes ()) {
1006+ $ narrowedType = new UnionType ([new ClassStringType (), new ObjectWithoutClassType ()]);
1007+ } elseif ((new ConstantIntegerType (1 ))->isSuperTypeOf ($ arrayKeyOffsetType )->yes ()) {
1008+ $ narrowedType = new IntersectionType ([new StringType (), new AccessoryNonFalsyStringType ()]);
1009+ } else {
1010+ $ narrowedType = new UnionType ([new IntersectionType ([new StringType (), new AccessoryNonFalsyStringType ()]), new ObjectWithoutClassType ()]);
10041011 }
1012+ $ result = TypeCombinator::intersect ($ result , $ narrowedType );
10051013 }
10061014
10071015 return $ result ;
0 commit comments