@@ -1065,71 +1065,74 @@ private function specifyTypesForCountFuncCall(
1065
1065
return null ;
1066
1066
}
1067
1067
1068
- $ resultType = TypeTraverser::map ($ type , static function (Type $ type , callable $ traverse ) use ($ sizeType , $ context ) {
1069
- if ($ type instanceof UnionType) {
1070
- return $ traverse ($ type );
1071
- }
1072
-
1073
- $ isSizeSuperTypeOfArraySize = $ sizeType ->isSuperTypeOf ($ type ->getArraySize ());
1068
+ $ resultTypes = [];
1069
+ $ innerTypes = $ type instanceof UnionType ? $ type ->getTypes () : [$ type ];
1070
+ foreach ($ innerTypes as $ innerType ) {
1071
+ $ isSizeSuperTypeOfArraySize = $ sizeType ->isSuperTypeOf ($ innerType ->getArraySize ());
1074
1072
if ($ isSizeSuperTypeOfArraySize ->no ()) {
1075
- return new NeverType () ;
1073
+ continue ;
1076
1074
}
1077
1075
if ($ context ->falsey () && $ isSizeSuperTypeOfArraySize ->maybe ()) {
1078
- return new NeverType () ;
1076
+ continue ;
1079
1077
}
1080
1078
1081
- if ($ type ->isList ()->yes ()) {
1082
- if (
1083
- $ sizeType instanceof ConstantIntegerType
1084
- && $ sizeType ->getValue () < ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT
1085
- ) {
1086
- // turn optional offsets non-optional
1087
- $ valueTypesBuilder = ConstantArrayTypeBuilder::createEmpty ();
1088
- for ($ i = 0 ; $ i < $ sizeType ->getValue (); $ i ++) {
1089
- $ offsetType = new ConstantIntegerType ($ i );
1090
- $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ type ->getOffsetValueType ($ offsetType ));
1091
- }
1092
- return $ valueTypesBuilder ->getArray ();
1079
+ if (
1080
+ $ innerType ->isList ()->yes ()
1081
+ && $ sizeType instanceof ConstantIntegerType
1082
+ && $ sizeType ->getValue () < ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT
1083
+ ) {
1084
+ // turn optional offsets non-optional
1085
+ $ valueTypesBuilder = ConstantArrayTypeBuilder::createEmpty ();
1086
+ for ($ i = 0 ; $ i < $ sizeType ->getValue (); $ i ++) {
1087
+ $ offsetType = new ConstantIntegerType ($ i );
1088
+ $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ innerType ->getOffsetValueType ($ offsetType ));
1093
1089
}
1090
+ $ resultTypes [] = $ valueTypesBuilder ->getArray ();
1091
+ continue ;
1092
+ }
1094
1093
1095
- if (
1096
- $ sizeType instanceof IntegerRangeType
1097
- && $ sizeType ->getMin () !== null
1098
- ) {
1099
- // turn optional offsets non-optional
1100
- $ valueTypesBuilder = ConstantArrayTypeBuilder::createEmpty ();
1101
- for ($ i = 0 ; $ i < $ sizeType ->getMin (); $ i ++) {
1094
+ if (
1095
+ $ innerType ->isList ()->yes ()
1096
+ && $ sizeType instanceof IntegerRangeType
1097
+ && $ sizeType ->getMin () !== null
1098
+ ) {
1099
+ // turn optional offsets non-optional
1100
+ $ valueTypesBuilder = ConstantArrayTypeBuilder::createEmpty ();
1101
+ for ($ i = 0 ; $ i < $ sizeType ->getMin (); $ i ++) {
1102
+ $ offsetType = new ConstantIntegerType ($ i );
1103
+ $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ innerType ->getOffsetValueType ($ offsetType ));
1104
+ }
1105
+ if ($ sizeType ->getMax () !== null ) {
1106
+ for ($ i = $ sizeType ->getMin (); $ i < $ sizeType ->getMax (); $ i ++) {
1102
1107
$ offsetType = new ConstantIntegerType ($ i );
1103
- $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ type ->getOffsetValueType ($ offsetType ));
1108
+ $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ innerType ->getOffsetValueType ($ offsetType ), true );
1104
1109
}
1105
- if ($ sizeType ->getMax () !== null ) {
1106
- for ($ i = $ sizeType ->getMin (); $ i < $ sizeType ->getMax (); $ i ++) {
1107
- $ offsetType = new ConstantIntegerType ($ i );
1108
- $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ type ->getOffsetValueType ($ offsetType ), true );
1109
- }
1110
- } elseif ($ type ->isConstantArray ()->yes ()) {
1111
- for ($ i = $ sizeType ->getMin ();; $ i ++) {
1112
- $ offsetType = new ConstantIntegerType ($ i );
1113
- $ hasOffset = $ type ->hasOffsetValueType ($ offsetType );
1114
- if ($ hasOffset ->no ()) {
1115
- break ;
1116
- }
1117
- $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ type ->getOffsetValueType ($ offsetType ), !$ hasOffset ->yes ());
1110
+ } elseif ($ innerType ->isConstantArray ()->yes ()) {
1111
+ for ($ i = $ sizeType ->getMin ();; $ i ++) {
1112
+ $ offsetType = new ConstantIntegerType ($ i );
1113
+ $ hasOffset = $ innerType ->hasOffsetValueType ($ offsetType );
1114
+ if ($ hasOffset ->no ()) {
1115
+ break ;
1118
1116
}
1119
- } else {
1120
- return TypeCombinator::intersect ($ type , new NonEmptyArrayType ());
1117
+ $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ innerType ->getOffsetValueType ($ offsetType ), !$ hasOffset ->yes ());
1121
1118
}
1122
-
1123
- return $ valueTypesBuilder ->getArray ();
1119
+ } else {
1120
+ $ resultTypes [] = TypeCombinator::intersect ($ innerType , new NonEmptyArrayType ());
1121
+ continue ;
1124
1122
}
1125
1123
1126
- return $ context ->truthy () ? $ type : new NeverType ();
1124
+ $ resultTypes [] = $ valueTypesBuilder ->getArray ();
1125
+ continue ;
1127
1126
}
1128
1127
1129
- return $ context ->truthy () ? TypeCombinator::intersect ($ type , new NonEmptyArrayType ()) : new NeverType ();
1130
- });
1128
+ if (!$ context ->truthy ()) {
1129
+ continue ;
1130
+ }
1131
+
1132
+ $ resultTypes [] = $ innerType ;
1133
+ }
1131
1134
1132
- return $ this ->create ($ countFuncCall ->getArgs ()[0 ]->value , $ resultType , $ context , $ scope )->setRootExpr ($ rootExpr );
1135
+ return $ this ->create ($ countFuncCall ->getArgs ()[0 ]->value , TypeCombinator:: union (... $ resultTypes ) , $ context , $ scope )->setRootExpr ($ rootExpr );
1133
1136
}
1134
1137
1135
1138
private function specifyTypesForConstantBinaryExpression (
0 commit comments