@@ -991,71 +991,74 @@ private function specifyTypesForCountFuncCall(
991
991
return null ;
992
992
}
993
993
994
- $ resultType = TypeTraverser::map ($ type , static function (Type $ type , callable $ traverse ) use ($ sizeType , $ context ) {
995
- if ($ type instanceof UnionType) {
996
- return $ traverse ($ type );
997
- }
998
-
999
- $ isSizeSuperTypeOfArraySize = $ sizeType ->isSuperTypeOf ($ type ->getArraySize ());
994
+ $ resultTypes = [];
995
+ $ innerTypes = $ type instanceof UnionType ? $ type ->getTypes () : [$ type ];
996
+ foreach ($ innerTypes as $ innerType ) {
997
+ $ isSizeSuperTypeOfArraySize = $ sizeType ->isSuperTypeOf ($ innerType ->getArraySize ());
1000
998
if ($ isSizeSuperTypeOfArraySize ->no ()) {
1001
- return new NeverType () ;
999
+ continue ;
1002
1000
}
1003
1001
if ($ context ->falsey () && $ isSizeSuperTypeOfArraySize ->maybe ()) {
1004
- return new NeverType () ;
1002
+ continue ;
1005
1003
}
1006
1004
1007
- if ($ type ->isList ()->yes ()) {
1008
- if (
1009
- $ sizeType instanceof ConstantIntegerType
1010
- && $ sizeType ->getValue () < ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT
1011
- ) {
1012
- // turn optional offsets non-optional
1013
- $ valueTypesBuilder = ConstantArrayTypeBuilder::createEmpty ();
1014
- for ($ i = 0 ; $ i < $ sizeType ->getValue (); $ i ++) {
1015
- $ offsetType = new ConstantIntegerType ($ i );
1016
- $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ type ->getOffsetValueType ($ offsetType ));
1017
- }
1018
- return $ valueTypesBuilder ->getArray ();
1005
+ if (
1006
+ $ innerType ->isList ()->yes ()
1007
+ && $ sizeType instanceof ConstantIntegerType
1008
+ && $ sizeType ->getValue () < ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT
1009
+ ) {
1010
+ // turn optional offsets non-optional
1011
+ $ valueTypesBuilder = ConstantArrayTypeBuilder::createEmpty ();
1012
+ for ($ i = 0 ; $ i < $ sizeType ->getValue (); $ i ++) {
1013
+ $ offsetType = new ConstantIntegerType ($ i );
1014
+ $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ innerType ->getOffsetValueType ($ offsetType ));
1019
1015
}
1016
+ $ resultTypes [] = $ valueTypesBuilder ->getArray ();
1017
+ continue ;
1018
+ }
1020
1019
1021
- if (
1022
- $ sizeType instanceof IntegerRangeType
1023
- && $ sizeType ->getMin () !== null
1024
- ) {
1025
- // turn optional offsets non-optional
1026
- $ valueTypesBuilder = ConstantArrayTypeBuilder::createEmpty ();
1027
- for ($ i = 0 ; $ i < $ sizeType ->getMin (); $ i ++) {
1020
+ if (
1021
+ $ innerType ->isList ()->yes ()
1022
+ && $ sizeType instanceof IntegerRangeType
1023
+ && $ sizeType ->getMin () !== null
1024
+ ) {
1025
+ // turn optional offsets non-optional
1026
+ $ valueTypesBuilder = ConstantArrayTypeBuilder::createEmpty ();
1027
+ for ($ i = 0 ; $ i < $ sizeType ->getMin (); $ i ++) {
1028
+ $ offsetType = new ConstantIntegerType ($ i );
1029
+ $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ innerType ->getOffsetValueType ($ offsetType ));
1030
+ }
1031
+ if ($ sizeType ->getMax () !== null ) {
1032
+ for ($ i = $ sizeType ->getMin (); $ i < $ sizeType ->getMax (); $ i ++) {
1028
1033
$ offsetType = new ConstantIntegerType ($ i );
1029
- $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ type ->getOffsetValueType ($ offsetType ));
1034
+ $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ innerType ->getOffsetValueType ($ offsetType ), true );
1030
1035
}
1031
- if ($ sizeType ->getMax () !== null ) {
1032
- for ($ i = $ sizeType ->getMin (); $ i < $ sizeType ->getMax (); $ i ++) {
1033
- $ offsetType = new ConstantIntegerType ($ i );
1034
- $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ type ->getOffsetValueType ($ offsetType ), true );
1035
- }
1036
- } elseif ($ type ->isConstantArray ()->yes ()) {
1037
- for ($ i = $ sizeType ->getMin ();; $ i ++) {
1038
- $ offsetType = new ConstantIntegerType ($ i );
1039
- $ hasOffset = $ type ->hasOffsetValueType ($ offsetType );
1040
- if ($ hasOffset ->no ()) {
1041
- break ;
1042
- }
1043
- $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ type ->getOffsetValueType ($ offsetType ), !$ hasOffset ->yes ());
1036
+ } elseif ($ innerType ->isConstantArray ()->yes ()) {
1037
+ for ($ i = $ sizeType ->getMin ();; $ i ++) {
1038
+ $ offsetType = new ConstantIntegerType ($ i );
1039
+ $ hasOffset = $ innerType ->hasOffsetValueType ($ offsetType );
1040
+ if ($ hasOffset ->no ()) {
1041
+ break ;
1044
1042
}
1045
- } else {
1046
- return TypeCombinator::intersect ($ type , new NonEmptyArrayType ());
1043
+ $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ innerType ->getOffsetValueType ($ offsetType ), !$ hasOffset ->yes ());
1047
1044
}
1048
-
1049
- return $ valueTypesBuilder ->getArray ();
1045
+ } else {
1046
+ $ resultTypes [] = TypeCombinator::intersect ($ innerType , new NonEmptyArrayType ());
1047
+ continue ;
1050
1048
}
1051
1049
1052
- return $ context ->truthy () ? $ type : new NeverType ();
1050
+ $ resultTypes [] = $ valueTypesBuilder ->getArray ();
1051
+ continue ;
1053
1052
}
1054
1053
1055
- return $ context ->truthy () ? TypeCombinator::intersect ($ type , new NonEmptyArrayType ()) : new NeverType ();
1056
- });
1054
+ if (!$ context ->truthy ()) {
1055
+ continue ;
1056
+ }
1057
+
1058
+ $ resultTypes [] = $ innerType ;
1059
+ }
1057
1060
1058
- return $ this ->create ($ countFuncCall ->getArgs ()[0 ]->value , $ resultType , $ context , $ scope )->setRootExpr ($ rootExpr );
1061
+ return $ this ->create ($ countFuncCall ->getArgs ()[0 ]->value , TypeCombinator:: union (... $ resultTypes ) , $ context , $ scope )->setRootExpr ($ rootExpr );
1059
1062
}
1060
1063
1061
1064
private function specifyTypesForConstantBinaryExpression (
0 commit comments