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