@@ -784,6 +784,9 @@ public function getArraySize(): Type
784784
785785 public function getIterableKeyType (): Type
786786 {
787+ if ($ this ->isCallable ()->yes () && $ this ->isArray ()->yes ()) {
788+ return new UnionType ([new ConstantIntegerType (0 ), new ConstantIntegerType (1 )]);
789+ }
787790 return $ this ->intersectTypes (static fn (Type $ type ): Type => $ type ->getIterableKeyType ());
788791 }
789792
@@ -799,7 +802,17 @@ public function getLastIterableKeyType(): Type
799802
800803 public function getIterableValueType (): Type
801804 {
802- return $ this ->intersectTypes (static fn (Type $ type ): Type => $ type ->getIterableValueType ());
805+ $ result = $ this ->intersectTypes (static fn (Type $ type ): Type => $ type ->getIterableValueType ());
806+ if ($ this ->isCallable ()->yes () && $ this ->isArray ()->yes ()) {
807+ return TypeCombinator::intersect (
808+ $ result ,
809+ new UnionType ([
810+ new ObjectWithoutClassType (),
811+ new IntersectionType ([new StringType (), new AccessoryNonFalsyStringType ()]),
812+ ]),
813+ );
814+ }
815+ return $ result ;
803816 }
804817
805818 public function getFirstIterableValueType (): Type
@@ -967,17 +980,15 @@ private function doHasOffsetValueType(Type $offsetType): TrinaryLogic
967980 }
968981 }
969982
970- $ result = $ this ->intersectResults (static fn (Type $ type ): TrinaryLogic => $ type ->hasOffsetValueType ($ offsetType ));
971-
972- if (!$ result ->yes () && $ this ->isCallable ()->yes () && $ this ->isArray ()->yes ()) {
983+ if ($ this ->isCallable ()->yes () && $ this ->isArray ()->yes ()) {
973984 $ arrayKeyOffsetType = $ offsetType ->toArrayKey ();
974985 $ callableArrayOffsetType = new UnionType ([new ConstantIntegerType (0 ), new ConstantIntegerType (1 )]);
975986 if ($ callableArrayOffsetType ->isSuperTypeOf ($ arrayKeyOffsetType )->yes ()) {
976987 return TrinaryLogic::createYes ();
977988 }
978989 }
979990
980- return $ result ;
991+ return $ this -> intersectResults ( static fn ( Type $ type ): TrinaryLogic => $ type -> hasOffsetValueType ( $ offsetType )) ;
981992 }
982993
983994 public function getOffsetValueType (Type $ offsetType ): Type
@@ -998,17 +1009,14 @@ private function doGetOffsetValueType(Type $offsetType): Type
9981009
9991010 if ($ this ->isCallable ()->yes () && $ this ->isArray ()->yes ()) {
10001011 $ arrayKeyOffsetType = $ offsetType ->toArrayKey ();
1001- $ callableArrayOffsetType = new UnionType ([new ConstantIntegerType (0 ), new ConstantIntegerType (1 )]);
1002- if ($ callableArrayOffsetType ->isSuperTypeOf ($ arrayKeyOffsetType )->yes ()) {
1003- if ((new ConstantIntegerType (0 ))->isSuperTypeOf ($ arrayKeyOffsetType )->yes ()) {
1004- $ narrowedType = new UnionType ([new ClassStringType (), new ObjectWithoutClassType ()]);
1005- } elseif ((new ConstantIntegerType (1 ))->isSuperTypeOf ($ arrayKeyOffsetType )->yes ()) {
1006- $ narrowedType = new StringType ();
1007- } else {
1008- $ narrowedType = new UnionType ([new StringType (), new ObjectWithoutClassType ()]);
1009- }
1010- $ result = TypeCombinator::intersect ($ result , $ narrowedType );
1012+ if ((new ConstantIntegerType (0 ))->isSuperTypeOf ($ arrayKeyOffsetType )->yes ()) {
1013+ $ narrowedType = new UnionType ([new ClassStringType (), new ObjectWithoutClassType ()]);
1014+ } elseif ((new ConstantIntegerType (1 ))->isSuperTypeOf ($ arrayKeyOffsetType )->yes ()) {
1015+ $ narrowedType = new IntersectionType ([new StringType (), new AccessoryNonFalsyStringType ()]);
1016+ } else {
1017+ $ narrowedType = new UnionType ([new IntersectionType ([new StringType (), new AccessoryNonFalsyStringType ()]), new ObjectWithoutClassType ()]);
10111018 }
1019+ $ result = TypeCombinator::intersect ($ result , $ narrowedType );
10121020 }
10131021
10141022 return $ result ;
0 commit comments