@@ -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 (
@@ -972,66 +970,52 @@ public function specifyTypesInCondition(
972
970
return (new SpecifiedTypes ([], []))->setRootExpr ($ expr );
973
971
}
974
972
975
- private function narrowUnionByArraySize (FuncCall $ countFuncCall , UnionType $ argType , ?Type $ sizeType , TypeSpecifierContext $ context , Scope $ scope , ?Expr $ rootExpr ): ?SpecifiedTypes
973
+ private function specifyTypesForCountFuncCall (FuncCall $ countFuncCall , Type $ type , ?Type $ sizeType , TypeSpecifierContext $ context , Scope $ scope , ?Expr $ rootExpr ): ?SpecifiedTypes
976
974
{
977
975
if ($ sizeType === null ) {
978
976
return null ;
979
977
}
980
978
981
- if (count ($ countFuncCall ->getArgs ()) === 1 ) {
982
- $ isNormalCount = TrinaryLogic::createYes ();
983
- } else {
984
- $ mode = $ scope ->getType ($ countFuncCall ->getArgs ()[1 ]->value );
985
- $ isNormalCount = (new ConstantIntegerType (COUNT_NORMAL ))->isSuperTypeOf ($ mode )->result ->or ($ argType ->getIterableValueType ()->isArray ()->negate ());
986
- }
987
-
988
979
if (
989
- $ isNormalCount ->yes ()
990
- && $ argType ->isConstantArray ()->yes ()
980
+ $ this -> isFuncCallWithNormalCount ( $ countFuncCall , $ scope ) ->yes ()
981
+ && $ type ->isConstantArray ()->yes ()
991
982
) {
992
- $ result = [];
993
- foreach ($ argType ->getTypes () as $ innerType ) {
994
- $ arraySize = $ innerType ->getArraySize ();
983
+ $ resultType = TypeTraverser::map ($ type , function (Type $ type , callable $ traverse ) use ($ sizeType , $ context ) {
984
+ if ($ type instanceof UnionType) {
985
+ return $ traverse ($ type );
986
+ }
987
+
988
+ $ arraySize = $ type ->getArraySize ();
995
989
$ isSize = $ sizeType ->isSuperTypeOf ($ arraySize );
996
990
if ($ context ->truthy ()) {
997
991
if ($ isSize ->no ()) {
998
- continue ;
992
+ return new NeverType () ;
999
993
}
1000
994
1001
- $ constArray = $ this ->turnListIntoConstantArray ($ countFuncCall , $ innerType , $ sizeType, $ scope );
995
+ $ constArray = $ this ->turnListIntoConstantArray ($ type , $ sizeType );
1002
996
if ($ constArray !== null ) {
1003
- $ innerType = $ constArray ;
997
+ $ type = $ constArray ;
1004
998
}
1005
999
}
1006
1000
if ($ context ->falsey ()) {
1007
1001
if (!$ isSize ->yes ()) {
1008
- continue ;
1002
+ return new NeverType () ;
1009
1003
}
1010
1004
}
1011
1005
1012
- $ result [] = $ innerType ;
1013
- }
1006
+ return $ type ;
1007
+ });
1014
1008
1015
- return $ this ->create ($ countFuncCall ->getArgs ()[0 ]->value , TypeCombinator:: union (... $ result ) , $ context , $ scope )->setRootExpr ($ rootExpr );
1009
+ return $ this ->create ($ countFuncCall ->getArgs ()[0 ]->value , $ resultType , $ context , $ scope )->setRootExpr ($ rootExpr );
1016
1010
}
1017
1011
1018
1012
return null ;
1019
1013
}
1020
1014
1021
- private function turnListIntoConstantArray (FuncCall $ countFuncCall , Type $ type , Type $ sizeType, Scope $ scope ): ?Type
1015
+ private function turnListIntoConstantArray (Type $ type , Type $ sizeType ): ?Type
1022
1016
{
1023
- $ argType = $ scope ->getType ($ countFuncCall ->getArgs ()[0 ]->value );
1024
-
1025
- if (count ($ countFuncCall ->getArgs ()) === 1 ) {
1026
- $ isNormalCount = TrinaryLogic::createYes ();
1027
- } else {
1028
- $ mode = $ scope ->getType ($ countFuncCall ->getArgs ()[1 ]->value );
1029
- $ isNormalCount = (new ConstantIntegerType (COUNT_NORMAL ))->isSuperTypeOf ($ mode )->result ->or ($ argType ->getIterableValueType ()->isArray ()->negate ());
1030
- }
1031
-
1032
1017
if (
1033
- $ isNormalCount ->yes ()
1034
- && $ type ->isList ()->yes ()
1018
+ $ type ->isList ()->yes ()
1035
1019
&& $ sizeType instanceof ConstantIntegerType
1036
1020
&& $ sizeType ->getValue () < ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT
1037
1021
) {
@@ -1045,8 +1029,7 @@ private function turnListIntoConstantArray(FuncCall $countFuncCall, Type $type,
1045
1029
}
1046
1030
1047
1031
if (
1048
- $ isNormalCount ->yes ()
1049
- && $ type ->isList ()->yes ()
1032
+ $ type ->isList ()->yes ()
1050
1033
&& $ sizeType instanceof IntegerRangeType
1051
1034
&& $ sizeType ->getMin () !== null
1052
1035
) {
@@ -1083,6 +1066,18 @@ private function turnListIntoConstantArray(FuncCall $countFuncCall, Type $type,
1083
1066
return null ;
1084
1067
}
1085
1068
1069
+ private function isFuncCallWithNormalCount (FuncCall $ countFuncCall , Scope $ scope ): TrinaryLogic
1070
+ {
1071
+ $ argType = $ scope ->getType ($ countFuncCall ->getArgs ()[0 ]->value );
1072
+
1073
+ if (count ($ countFuncCall ->getArgs ()) === 1 ) {
1074
+ return TrinaryLogic::createYes ();
1075
+ }
1076
+ $ mode = $ scope ->getType ($ countFuncCall ->getArgs ()[1 ]->value );
1077
+
1078
+ return (new ConstantIntegerType (COUNT_NORMAL ))->isSuperTypeOf ($ mode )->result ->or ($ argType ->getIterableValueType ()->isArray ()->negate ());
1079
+ }
1080
+
1086
1081
private function specifyTypesForConstantBinaryExpression (
1087
1082
Expr $ exprNode ,
1088
1083
Type $ constantType ,
@@ -2112,11 +2107,9 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty
2112
2107
);
2113
2108
}
2114
2109
2115
- if ($ argType instanceof UnionType) {
2116
- $ narrowed = $ this ->narrowUnionByArraySize ($ unwrappedLeftExpr , $ argType , $ rightType , $ context , $ scope , $ expr );
2117
- if ($ narrowed !== null ) {
2118
- return $ narrowed ;
2119
- }
2110
+ $ specifiedTypes = $ this ->specifyTypesForCountFuncCall ($ unwrappedLeftExpr , $ argType , $ rightType , $ context , $ scope , $ expr );
2111
+ if ($ specifiedTypes !== null ) {
2112
+ return $ specifiedTypes ;
2120
2113
}
2121
2114
2122
2115
if ($ context ->truthy ()) {
@@ -2129,7 +2122,8 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty
2129
2122
}
2130
2123
2131
2124
$ funcTypes = $ this ->create ($ unwrappedLeftExpr , $ rightType , $ context , $ scope )->setRootExpr ($ expr );
2132
- $ constArray = $ this ->turnListIntoConstantArray ($ unwrappedLeftExpr , $ argType , $ rightType , $ scope );
2125
+ $ isNormalCount = $ this ->isFuncCallWithNormalCount ($ unwrappedLeftExpr , $ scope );
2126
+ $ constArray = $ isNormalCount ->yes () ? $ this ->turnListIntoConstantArray ($ argType , $ rightType ) : null ;
2133
2127
if ($ constArray !== null ) {
2134
2128
return $ funcTypes ->unionWith (
2135
2129
$ this ->create ($ unwrappedLeftExpr ->getArgs ()[0 ]->value , $ constArray , $ context , $ scope )->setRootExpr ($ expr ),
0 commit comments