@@ -272,22 +272,20 @@ public function specifyTypesInCondition(
272
272
) {
273
273
$ argType = $ scope ->getType ($ expr ->right ->getArgs ()[0 ]->value );
274
274
275
- if ($ argType instanceof UnionType) {
276
- $ sizeType = null ;
277
- if ($ leftType instanceof ConstantIntegerType) {
278
- if ($ orEqual ) {
279
- $ sizeType = IntegerRangeType::createAllGreaterThanOrEqualTo ($ leftType ->getValue ());
280
- } else {
281
- $ sizeType = IntegerRangeType::createAllGreaterThan ($ leftType ->getValue ());
282
- }
283
- } elseif ($ leftType instanceof IntegerRangeType) {
284
- $ sizeType = $ leftType ;
275
+ $ sizeType = null ;
276
+ if ($ leftType instanceof ConstantIntegerType) {
277
+ if ($ orEqual ) {
278
+ $ sizeType = IntegerRangeType::createAllGreaterThanOrEqualTo ($ leftType ->getValue ());
279
+ } else {
280
+ $ sizeType = IntegerRangeType::createAllGreaterThan ($ leftType ->getValue ());
285
281
}
282
+ } elseif ($ leftType instanceof IntegerRangeType) {
283
+ $ sizeType = $ leftType ;
284
+ }
286
285
287
- $ narrowed = $ this ->narrowUnionByArraySize ($ expr ->right , $ argType , $ sizeType , $ context , $ scope , $ expr );
288
- if ($ narrowed !== null ) {
289
- return $ narrowed ;
290
- }
286
+ $ specifiedTypes = $ this ->specifyTypesForCountFuncCall ($ expr ->right , $ argType , $ sizeType , $ context , $ scope , $ expr );
287
+ if ($ specifiedTypes !== null ) {
288
+ $ result = $ result ->unionWith ($ specifiedTypes );
291
289
}
292
290
293
291
if (
@@ -1046,66 +1044,52 @@ public function specifyTypesInCondition(
1046
1044
return (new SpecifiedTypes ([], []))->setRootExpr ($ expr );
1047
1045
}
1048
1046
1049
- private function narrowUnionByArraySize (FuncCall $ countFuncCall , UnionType $ argType , ?Type $ sizeType , TypeSpecifierContext $ context , Scope $ scope , ?Expr $ rootExpr ): ?SpecifiedTypes
1047
+ private function specifyTypesForCountFuncCall (FuncCall $ countFuncCall , Type $ type , ?Type $ sizeType , TypeSpecifierContext $ context , Scope $ scope , ?Expr $ rootExpr ): ?SpecifiedTypes
1050
1048
{
1051
1049
if ($ sizeType === null ) {
1052
1050
return null ;
1053
1051
}
1054
1052
1055
- if (count ($ countFuncCall ->getArgs ()) === 1 ) {
1056
- $ isNormalCount = TrinaryLogic::createYes ();
1057
- } else {
1058
- $ mode = $ scope ->getType ($ countFuncCall ->getArgs ()[1 ]->value );
1059
- $ isNormalCount = (new ConstantIntegerType (COUNT_NORMAL ))->isSuperTypeOf ($ mode )->result ->or ($ argType ->getIterableValueType ()->isArray ()->negate ());
1060
- }
1061
-
1062
1053
if (
1063
- $ isNormalCount ->yes ()
1064
- && $ argType ->isConstantArray ()->yes ()
1054
+ $ this -> isFuncCallWithNormalCount ( $ countFuncCall , $ scope ) ->yes ()
1055
+ && $ type ->isConstantArray ()->yes ()
1065
1056
) {
1066
- $ result = [];
1067
- foreach ($ argType ->getTypes () as $ innerType ) {
1068
- $ arraySize = $ innerType ->getArraySize ();
1057
+ $ resultType = TypeTraverser::map ($ type , function (Type $ type , callable $ traverse ) use ($ sizeType , $ context ) {
1058
+ if ($ type instanceof UnionType) {
1059
+ return $ traverse ($ type );
1060
+ }
1061
+
1062
+ $ arraySize = $ type ->getArraySize ();
1069
1063
$ isSize = $ sizeType ->isSuperTypeOf ($ arraySize );
1070
1064
if ($ context ->truthy ()) {
1071
1065
if ($ isSize ->no ()) {
1072
- continue ;
1066
+ return new NeverType () ;
1073
1067
}
1074
1068
1075
- $ constArray = $ this ->turnListIntoConstantArray ($ countFuncCall , $ innerType , $ sizeType, $ scope );
1069
+ $ constArray = $ this ->turnListIntoConstantArray ($ type , $ sizeType );
1076
1070
if ($ constArray !== null ) {
1077
- $ innerType = $ constArray ;
1071
+ $ type = $ constArray ;
1078
1072
}
1079
1073
}
1080
1074
if ($ context ->falsey ()) {
1081
1075
if (!$ isSize ->yes ()) {
1082
- continue ;
1076
+ return new NeverType () ;
1083
1077
}
1084
1078
}
1085
1079
1086
- $ result [] = $ innerType ;
1087
- }
1080
+ return $ type ;
1081
+ });
1088
1082
1089
- return $ this ->create ($ countFuncCall ->getArgs ()[0 ]->value , TypeCombinator:: union (... $ result ) , $ context , $ scope )->setRootExpr ($ rootExpr );
1083
+ return $ this ->create ($ countFuncCall ->getArgs ()[0 ]->value , $ resultType , $ context , $ scope )->setRootExpr ($ rootExpr );
1090
1084
}
1091
1085
1092
1086
return null ;
1093
1087
}
1094
1088
1095
- private function turnListIntoConstantArray (FuncCall $ countFuncCall , Type $ type , Type $ sizeType, Scope $ scope ): ?Type
1089
+ private function turnListIntoConstantArray (Type $ type , Type $ sizeType ): ?Type
1096
1090
{
1097
- $ argType = $ scope ->getType ($ countFuncCall ->getArgs ()[0 ]->value );
1098
-
1099
- if (count ($ countFuncCall ->getArgs ()) === 1 ) {
1100
- $ isNormalCount = TrinaryLogic::createYes ();
1101
- } else {
1102
- $ mode = $ scope ->getType ($ countFuncCall ->getArgs ()[1 ]->value );
1103
- $ isNormalCount = (new ConstantIntegerType (COUNT_NORMAL ))->isSuperTypeOf ($ mode )->result ->or ($ argType ->getIterableValueType ()->isArray ()->negate ());
1104
- }
1105
-
1106
1091
if (
1107
- $ isNormalCount ->yes ()
1108
- && $ type ->isList ()->yes ()
1092
+ $ type ->isList ()->yes ()
1109
1093
&& $ sizeType instanceof ConstantIntegerType
1110
1094
&& $ sizeType ->getValue () < ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT
1111
1095
) {
@@ -1119,8 +1103,7 @@ private function turnListIntoConstantArray(FuncCall $countFuncCall, Type $type,
1119
1103
}
1120
1104
1121
1105
if (
1122
- $ isNormalCount ->yes ()
1123
- && $ type ->isList ()->yes ()
1106
+ $ type ->isList ()->yes ()
1124
1107
&& $ sizeType instanceof IntegerRangeType
1125
1108
&& $ sizeType ->getMin () !== null
1126
1109
) {
@@ -1157,6 +1140,18 @@ private function turnListIntoConstantArray(FuncCall $countFuncCall, Type $type,
1157
1140
return null ;
1158
1141
}
1159
1142
1143
+ private function isFuncCallWithNormalCount (FuncCall $ countFuncCall , Scope $ scope ): TrinaryLogic
1144
+ {
1145
+ $ argType = $ scope ->getType ($ countFuncCall ->getArgs ()[0 ]->value );
1146
+
1147
+ if (count ($ countFuncCall ->getArgs ()) === 1 ) {
1148
+ return TrinaryLogic::createYes ();
1149
+ }
1150
+ $ mode = $ scope ->getType ($ countFuncCall ->getArgs ()[1 ]->value );
1151
+
1152
+ return (new ConstantIntegerType (COUNT_NORMAL ))->isSuperTypeOf ($ mode )->result ->or ($ argType ->getIterableValueType ()->isArray ()->negate ());
1153
+ }
1154
+
1160
1155
private function specifyTypesForConstantBinaryExpression (
1161
1156
Expr $ exprNode ,
1162
1157
Type $ constantType ,
@@ -2186,11 +2181,9 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty
2186
2181
);
2187
2182
}
2188
2183
2189
- if ($ argType instanceof UnionType) {
2190
- $ narrowed = $ this ->narrowUnionByArraySize ($ unwrappedLeftExpr , $ argType , $ rightType , $ context , $ scope , $ expr );
2191
- if ($ narrowed !== null ) {
2192
- return $ narrowed ;
2193
- }
2184
+ $ specifiedTypes = $ this ->specifyTypesForCountFuncCall ($ unwrappedLeftExpr , $ argType , $ rightType , $ context , $ scope , $ expr );
2185
+ if ($ specifiedTypes !== null ) {
2186
+ return $ specifiedTypes ;
2194
2187
}
2195
2188
2196
2189
if ($ context ->truthy ()) {
@@ -2203,7 +2196,8 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty
2203
2196
}
2204
2197
2205
2198
$ funcTypes = $ this ->create ($ unwrappedLeftExpr , $ rightType , $ context , $ scope )->setRootExpr ($ expr );
2206
- $ constArray = $ this ->turnListIntoConstantArray ($ unwrappedLeftExpr , $ argType , $ rightType , $ scope );
2199
+ $ isNormalCount = $ this ->isFuncCallWithNormalCount ($ unwrappedLeftExpr , $ scope );
2200
+ $ constArray = $ isNormalCount ->yes () ? $ this ->turnListIntoConstantArray ($ argType , $ rightType ) : null ;
2207
2201
if ($ constArray !== null ) {
2208
2202
return $ funcTypes ->unionWith (
2209
2203
$ this ->create ($ unwrappedLeftExpr ->getArgs ()[0 ]->value , $ constArray , $ context , $ scope )->setRootExpr ($ expr ),
0 commit comments