@@ -269,22 +269,20 @@ public function specifyTypesInCondition(
269269 ) {
270270 $ argType = $ scope ->getType ($ expr ->right ->getArgs ()[0 ]->value );
271271
272- if ($ argType instanceof UnionType) {
273- $ sizeType = null ;
274- if ($ leftType instanceof ConstantIntegerType) {
275- if ($ orEqual ) {
276- $ sizeType = IntegerRangeType::createAllGreaterThanOrEqualTo ($ leftType ->getValue ());
277- } else {
278- $ sizeType = IntegerRangeType::createAllGreaterThan ($ leftType ->getValue ());
279- }
280- } elseif ($ leftType instanceof IntegerRangeType) {
281- $ sizeType = $ leftType ;
272+ $ sizeType = null ;
273+ if ($ leftType instanceof ConstantIntegerType) {
274+ if ($ orEqual ) {
275+ $ sizeType = IntegerRangeType::createAllGreaterThanOrEqualTo ($ leftType ->getValue ());
276+ } else {
277+ $ sizeType = IntegerRangeType::createAllGreaterThan ($ leftType ->getValue ());
282278 }
279+ } elseif ($ leftType instanceof IntegerRangeType) {
280+ $ sizeType = $ leftType ;
281+ }
283282
284- $ narrowed = $ this ->narrowUnionByArraySize ($ expr ->right , $ argType , $ sizeType , $ context , $ scope , $ expr );
285- if ($ narrowed !== null ) {
286- return $ narrowed ;
287- }
283+ $ specifiedTypes = $ this ->specifyTypesForCountFuncCall ($ expr ->right , $ argType , $ sizeType , $ context , $ scope , $ expr );
284+ if ($ specifiedTypes !== null ) {
285+ $ result = $ result ->unionWith ($ specifiedTypes );
288286 }
289287
290288 if (
@@ -969,66 +967,52 @@ public function specifyTypesInCondition(
969967 return (new SpecifiedTypes ([], []))->setRootExpr ($ expr );
970968 }
971969
972- private function narrowUnionByArraySize (FuncCall $ countFuncCall , UnionType $ argType , ?Type $ sizeType , TypeSpecifierContext $ context , Scope $ scope , ?Expr $ rootExpr ): ?SpecifiedTypes
970+ private function specifyTypesForCountFuncCall (FuncCall $ countFuncCall , Type $ type , ?Type $ sizeType , TypeSpecifierContext $ context , Scope $ scope , ?Expr $ rootExpr ): ?SpecifiedTypes
973971 {
974972 if ($ sizeType === null ) {
975973 return null ;
976974 }
977975
978- if (count ($ countFuncCall ->getArgs ()) === 1 ) {
979- $ isNormalCount = TrinaryLogic::createYes ();
980- } else {
981- $ mode = $ scope ->getType ($ countFuncCall ->getArgs ()[1 ]->value );
982- $ isNormalCount = (new ConstantIntegerType (COUNT_NORMAL ))->isSuperTypeOf ($ mode )->result ->or ($ argType ->getIterableValueType ()->isArray ()->negate ());
983- }
984-
985976 if (
986- $ isNormalCount ->yes ()
987- && $ argType ->isConstantArray ()->yes ()
977+ $ this -> isFuncCallWithNormalCount ( $ countFuncCall , $ scope ) ->yes ()
978+ && $ type ->isConstantArray ()->yes ()
988979 ) {
989- $ result = [];
990- foreach ($ argType ->getTypes () as $ innerType ) {
991- $ arraySize = $ innerType ->getArraySize ();
980+ $ resultType = TypeTraverser::map ($ type , function (Type $ type , callable $ traverse ) use ($ sizeType , $ context ) {
981+ if ($ type instanceof UnionType) {
982+ return $ traverse ($ type );
983+ }
984+
985+ $ arraySize = $ type ->getArraySize ();
992986 $ isSize = $ sizeType ->isSuperTypeOf ($ arraySize );
993987 if ($ context ->truthy ()) {
994988 if ($ isSize ->no ()) {
995- continue ;
989+ return new NeverType () ;
996990 }
997991
998- $ constArray = $ this ->turnListIntoConstantArray ($ countFuncCall , $ innerType , $ sizeType, $ scope );
992+ $ constArray = $ this ->turnListIntoConstantArray ($ type , $ sizeType );
999993 if ($ constArray !== null ) {
1000- $ innerType = $ constArray ;
994+ $ type = $ constArray ;
1001995 }
1002996 }
1003997 if ($ context ->falsey ()) {
1004998 if (!$ isSize ->yes ()) {
1005- continue ;
999+ return new NeverType () ;
10061000 }
10071001 }
10081002
1009- $ result [] = $ innerType ;
1010- }
1003+ return $ type ;
1004+ });
10111005
1012- return $ this ->create ($ countFuncCall ->getArgs ()[0 ]->value , TypeCombinator:: union (... $ result ) , $ context , $ scope )->setRootExpr ($ rootExpr );
1006+ return $ this ->create ($ countFuncCall ->getArgs ()[0 ]->value , $ resultType , $ context , $ scope )->setRootExpr ($ rootExpr );
10131007 }
10141008
10151009 return null ;
10161010 }
10171011
1018- private function turnListIntoConstantArray (FuncCall $ countFuncCall , Type $ type , Type $ sizeType, Scope $ scope ): ?Type
1012+ private function turnListIntoConstantArray (Type $ type , Type $ sizeType ): ?Type
10191013 {
1020- $ argType = $ scope ->getType ($ countFuncCall ->getArgs ()[0 ]->value );
1021-
1022- if (count ($ countFuncCall ->getArgs ()) === 1 ) {
1023- $ isNormalCount = TrinaryLogic::createYes ();
1024- } else {
1025- $ mode = $ scope ->getType ($ countFuncCall ->getArgs ()[1 ]->value );
1026- $ isNormalCount = (new ConstantIntegerType (COUNT_NORMAL ))->isSuperTypeOf ($ mode )->result ->or ($ argType ->getIterableValueType ()->isArray ()->negate ());
1027- }
1028-
10291014 if (
1030- $ isNormalCount ->yes ()
1031- && $ type ->isList ()->yes ()
1015+ $ type ->isList ()->yes ()
10321016 && $ sizeType instanceof ConstantIntegerType
10331017 && $ sizeType ->getValue () < ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT
10341018 ) {
@@ -1042,8 +1026,7 @@ private function turnListIntoConstantArray(FuncCall $countFuncCall, Type $type,
10421026 }
10431027
10441028 if (
1045- $ isNormalCount ->yes ()
1046- && $ type ->isList ()->yes ()
1029+ $ type ->isList ()->yes ()
10471030 && $ sizeType instanceof IntegerRangeType
10481031 && $ sizeType ->getMin () !== null
10491032 ) {
@@ -1080,6 +1063,18 @@ private function turnListIntoConstantArray(FuncCall $countFuncCall, Type $type,
10801063 return null ;
10811064 }
10821065
1066+ private function isFuncCallWithNormalCount (FuncCall $ countFuncCall , Scope $ scope ): TrinaryLogic
1067+ {
1068+ $ argType = $ scope ->getType ($ countFuncCall ->getArgs ()[0 ]->value );
1069+
1070+ if (count ($ countFuncCall ->getArgs ()) === 1 ) {
1071+ return TrinaryLogic::createYes ();
1072+ }
1073+ $ mode = $ scope ->getType ($ countFuncCall ->getArgs ()[1 ]->value );
1074+
1075+ return (new ConstantIntegerType (COUNT_NORMAL ))->isSuperTypeOf ($ mode )->result ->or ($ argType ->getIterableValueType ()->isArray ()->negate ());
1076+ }
1077+
10831078 private function specifyTypesForConstantBinaryExpression (
10841079 Expr $ exprNode ,
10851080 Type $ constantType ,
@@ -2109,11 +2104,9 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty
21092104 );
21102105 }
21112106
2112- if ($ argType instanceof UnionType) {
2113- $ narrowed = $ this ->narrowUnionByArraySize ($ unwrappedLeftExpr , $ argType , $ rightType , $ context , $ scope , $ expr );
2114- if ($ narrowed !== null ) {
2115- return $ narrowed ;
2116- }
2107+ $ specifiedTypes = $ this ->specifyTypesForCountFuncCall ($ unwrappedLeftExpr , $ argType , $ rightType , $ context , $ scope , $ expr );
2108+ if ($ specifiedTypes !== null ) {
2109+ return $ specifiedTypes ;
21172110 }
21182111
21192112 if ($ context ->truthy ()) {
@@ -2126,7 +2119,8 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty
21262119 }
21272120
21282121 $ funcTypes = $ this ->create ($ unwrappedLeftExpr , $ rightType , $ context , $ scope )->setRootExpr ($ expr );
2129- $ constArray = $ this ->turnListIntoConstantArray ($ unwrappedLeftExpr , $ argType , $ rightType , $ scope );
2122+ $ isNormalCount = $ this ->isFuncCallWithNormalCount ($ unwrappedLeftExpr , $ scope );
2123+ $ constArray = $ isNormalCount ->yes () ? $ this ->turnListIntoConstantArray ($ argType , $ rightType ) : null ;
21302124 if ($ constArray !== null ) {
21312125 return $ funcTypes ->unionWith (
21322126 $ this ->create ($ unwrappedLeftExpr ->getArgs ()[0 ]->value , $ constArray , $ context , $ scope )->setRootExpr ($ expr ),
0 commit comments