@@ -277,22 +277,20 @@ public function specifyTypesInCondition(
277
277
) {
278
278
$ argType = $ scope ->getType ($ expr ->right ->getArgs ()[0 ]->value );
279
279
280
- if ($ argType instanceof UnionType) {
281
- $ sizeType = null ;
282
- if ($ leftType instanceof ConstantIntegerType) {
283
- if ($ orEqual ) {
284
- $ sizeType = IntegerRangeType::createAllGreaterThanOrEqualTo ($ leftType ->getValue ());
285
- } else {
286
- $ sizeType = IntegerRangeType::createAllGreaterThan ($ leftType ->getValue ());
287
- }
288
- } elseif ($ leftType instanceof IntegerRangeType) {
289
- $ sizeType = $ leftType ;
280
+ $ sizeType = null ;
281
+ if ($ leftType instanceof ConstantIntegerType) {
282
+ if ($ orEqual ) {
283
+ $ sizeType = IntegerRangeType::createAllGreaterThanOrEqualTo ($ leftType ->getValue ());
284
+ } else {
285
+ $ sizeType = IntegerRangeType::createAllGreaterThan ($ leftType ->getValue ());
290
286
}
287
+ } elseif ($ leftType instanceof IntegerRangeType) {
288
+ $ sizeType = $ leftType ;
289
+ }
291
290
292
- $ narrowed = $ this ->narrowUnionByArraySize ($ expr ->right , $ argType , $ sizeType , $ context , $ scope , $ rootExpr );
293
- if ($ narrowed !== null ) {
294
- return $ narrowed ;
295
- }
291
+ $ specifiedTypes = $ this ->specifyTypesForCountFuncCall ($ expr ->right , $ argType , $ sizeType , $ context , $ scope , $ rootExpr );
292
+ if ($ specifiedTypes !== null ) {
293
+ $ result = $ result ->unionWith ($ specifiedTypes );
296
294
}
297
295
298
296
if (
@@ -1010,66 +1008,64 @@ public function specifyTypesInCondition(
1010
1008
return new SpecifiedTypes ([], [], false , [], $ rootExpr );
1011
1009
}
1012
1010
1013
- private function narrowUnionByArraySize (FuncCall $ countFuncCall , UnionType $ argType , ?Type $ sizeType , TypeSpecifierContext $ context , Scope $ scope , ?Expr $ rootExpr ): ?SpecifiedTypes
1011
+ private function specifyTypesForCountFuncCall (FuncCall $ countFuncCall , Type $ type , ?Type $ sizeType , TypeSpecifierContext $ context , Scope $ scope , ?Expr $ rootExpr ): ?SpecifiedTypes
1014
1012
{
1015
1013
if ($ sizeType === null ) {
1016
1014
return null ;
1017
1015
}
1018
1016
1019
- if (count ($ countFuncCall ->getArgs ()) === 1 ) {
1020
- $ isNormalCount = TrinaryLogic::createYes ();
1021
- } else {
1022
- $ mode = $ scope ->getType ($ countFuncCall ->getArgs ()[1 ]->value );
1023
- $ isNormalCount = (new ConstantIntegerType (COUNT_NORMAL ))->isSuperTypeOf ($ mode )->or ($ argType ->getIterableValueType ()->isArray ()->negate ());
1024
- }
1025
-
1026
1017
if (
1027
- $ isNormalCount ->yes ()
1028
- && $ argType ->isConstantArray ()->yes ()
1018
+ $ this -> isNormalCount ( $ countFuncCall , $ scope ) ->yes ()
1019
+ && $ type ->isConstantArray ()->yes ()
1029
1020
) {
1030
- $ result = [];
1031
- foreach ($ argType ->getTypes () as $ innerType ) {
1032
- $ arraySize = $ innerType ->getArraySize ();
1021
+ $ resultType = TypeTraverser::map ($ type , function (Type $ type , callable $ traverse ) use ($ sizeType , $ context ) {
1022
+ if ($ type instanceof UnionType) {
1023
+ return $ traverse ($ type );
1024
+ }
1025
+
1026
+ $ arraySize = $ type ->getArraySize ();
1033
1027
$ isSize = $ sizeType ->isSuperTypeOf ($ arraySize );
1034
1028
if ($ context ->truthy ()) {
1035
1029
if ($ isSize ->no ()) {
1036
- continue ;
1030
+ return new NeverType () ;
1037
1031
}
1038
1032
1039
- $ constArray = $ this ->turnListIntoConstantArray ($ countFuncCall , $ innerType , $ sizeType, $ scope );
1033
+ $ constArray = $ this ->turnListIntoConstantArray ($ type , $ sizeType );
1040
1034
if ($ constArray !== null ) {
1041
- $ innerType = $ constArray ;
1035
+ $ type = $ constArray ;
1042
1036
}
1043
1037
}
1044
1038
if ($ context ->falsey ()) {
1045
1039
if (!$ isSize ->yes ()) {
1046
- continue ;
1040
+ return new NeverType () ;
1047
1041
}
1048
1042
}
1049
1043
1050
- $ result [] = $ innerType ;
1051
- }
1044
+ return $ type ;
1045
+ });
1052
1046
1053
- return $ this ->create ($ countFuncCall ->getArgs ()[0 ]->value , TypeCombinator:: union (... $ result ) , $ context , false , $ scope , $ rootExpr );
1047
+ return $ this ->create ($ countFuncCall ->getArgs ()[0 ]->value , $ resultType , $ context , false , $ scope , $ rootExpr );
1054
1048
}
1055
1049
1056
1050
return null ;
1057
1051
}
1058
1052
1059
- private function turnListIntoConstantArray (FuncCall $ countFuncCall , Type $ type , Type $ sizeType , Scope $ scope ): ? Type
1053
+ private function isNormalCount (FuncCall $ countFuncCall , Scope $ scope ): TrinaryLogic
1060
1054
{
1061
1055
$ argType = $ scope ->getType ($ countFuncCall ->getArgs ()[0 ]->value );
1062
1056
1063
1057
if (count ($ countFuncCall ->getArgs ()) === 1 ) {
1064
- $ isNormalCount = TrinaryLogic::createYes ();
1065
- } else {
1066
- $ mode = $ scope ->getType ($ countFuncCall ->getArgs ()[1 ]->value );
1067
- $ isNormalCount = (new ConstantIntegerType (COUNT_NORMAL ))->isSuperTypeOf ($ mode )->or ($ argType ->getIterableValueType ()->isArray ()->negate ());
1058
+ return TrinaryLogic::createYes ();
1068
1059
}
1060
+ $ mode = $ scope ->getType ($ countFuncCall ->getArgs ()[1 ]->value );
1061
+
1062
+ return (new ConstantIntegerType (COUNT_NORMAL ))->isSuperTypeOf ($ mode )->or ($ argType ->getIterableValueType ()->isArray ()->negate ());
1063
+ }
1069
1064
1065
+ private function turnListIntoConstantArray (Type $ type , Type $ sizeType ): ?Type
1066
+ {
1070
1067
if (
1071
- $ isNormalCount ->yes ()
1072
- && $ type ->isList ()->yes ()
1068
+ $ type ->isList ()->yes ()
1073
1069
&& $ sizeType instanceof ConstantIntegerType
1074
1070
&& $ sizeType ->getValue () < ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT
1075
1071
) {
@@ -1083,8 +1079,7 @@ private function turnListIntoConstantArray(FuncCall $countFuncCall, Type $type,
1083
1079
}
1084
1080
1085
1081
if (
1086
- $ isNormalCount ->yes ()
1087
- && $ type ->isList ()->yes ()
1082
+ $ type ->isList ()->yes ()
1088
1083
&& $ sizeType instanceof IntegerRangeType
1089
1084
&& $ sizeType ->getMin () !== null
1090
1085
) {
@@ -2171,11 +2166,9 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty
2171
2166
);
2172
2167
}
2173
2168
2174
- if ($ argType instanceof UnionType) {
2175
- $ narrowed = $ this ->narrowUnionByArraySize ($ unwrappedLeftExpr , $ argType , $ rightType , $ context , $ scope , $ rootExpr );
2176
- if ($ narrowed !== null ) {
2177
- return $ narrowed ;
2178
- }
2169
+ $ specifiedTypes = $ this ->specifyTypesForCountFuncCall ($ unwrappedLeftExpr , $ argType , $ rightType , $ context , $ scope , $ rootExpr );
2170
+ if ($ specifiedTypes !== null ) {
2171
+ return $ specifiedTypes ;
2179
2172
}
2180
2173
2181
2174
if ($ context ->truthy ()) {
@@ -2188,7 +2181,8 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty
2188
2181
}
2189
2182
2190
2183
$ funcTypes = $ this ->create ($ unwrappedLeftExpr , $ rightType , $ context , false , $ scope , $ rootExpr );
2191
- $ constArray = $ this ->turnListIntoConstantArray ($ unwrappedLeftExpr , $ argType , $ rightType , $ scope );
2184
+ $ isNormalCount = $ this ->isNormalCount ($ unwrappedLeftExpr , $ scope );
2185
+ $ constArray = $ isNormalCount ->yes () ? $ this ->turnListIntoConstantArray ($ argType , $ rightType ) : null ;
2192
2186
if ($ constArray !== null ) {
2193
2187
return $ funcTypes ->unionWith (
2194
2188
$ this ->create ($ unwrappedLeftExpr ->getArgs ()[0 ]->value , $ constArray , $ context , false , $ scope , $ rootExpr ),
0 commit comments