@@ -272,22 +272,20 @@ public function specifyTypesInCondition(
272272 ) {
273273 $ argType = $ scope ->getType ($ expr ->right ->getArgs ()[0 ]->value );
274274
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 ());
285281 }
282+ } elseif ($ leftType instanceof IntegerRangeType) {
283+ $ sizeType = $ leftType ;
284+ }
286285
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 );
291289 }
292290
293291 if (
@@ -972,66 +970,52 @@ public function specifyTypesInCondition(
972970 return (new SpecifiedTypes ([], []))->setRootExpr ($ expr );
973971 }
974972
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
976974 {
977975 if ($ sizeType === null ) {
978976 return null ;
979977 }
980978
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-
988979 if (
989- $ isNormalCount ->yes ()
990- && $ argType ->isConstantArray ()->yes ()
980+ $ this -> isFuncCallWithNormalCount ( $ countFuncCall , $ scope ) ->yes ()
981+ && $ type ->isConstantArray ()->yes ()
991982 ) {
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 ();
995989 $ isSize = $ sizeType ->isSuperTypeOf ($ arraySize );
996990 if ($ context ->truthy ()) {
997991 if ($ isSize ->no ()) {
998- continue ;
992+ return new NeverType () ;
999993 }
1000994
1001- $ constArray = $ this ->turnListIntoConstantArray ($ countFuncCall , $ innerType , $ sizeType, $ scope );
995+ $ constArray = $ this ->turnListIntoConstantArray ($ type , $ sizeType );
1002996 if ($ constArray !== null ) {
1003- $ innerType = $ constArray ;
997+ $ type = $ constArray ;
1004998 }
1005999 }
10061000 if ($ context ->falsey ()) {
10071001 if (!$ isSize ->yes ()) {
1008- continue ;
1002+ return new NeverType () ;
10091003 }
10101004 }
10111005
1012- $ result [] = $ innerType ;
1013- }
1006+ return $ type ;
1007+ });
10141008
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 );
10161010 }
10171011
10181012 return null ;
10191013 }
10201014
1021- private function turnListIntoConstantArray (FuncCall $ countFuncCall , Type $ type , Type $ sizeType, Scope $ scope ): ?Type
1015+ private function turnListIntoConstantArray (Type $ type , Type $ sizeType ): ?Type
10221016 {
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-
10321017 if (
1033- $ isNormalCount ->yes ()
1034- && $ type ->isList ()->yes ()
1018+ $ type ->isList ()->yes ()
10351019 && $ sizeType instanceof ConstantIntegerType
10361020 && $ sizeType ->getValue () < ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT
10371021 ) {
@@ -1045,8 +1029,7 @@ private function turnListIntoConstantArray(FuncCall $countFuncCall, Type $type,
10451029 }
10461030
10471031 if (
1048- $ isNormalCount ->yes ()
1049- && $ type ->isList ()->yes ()
1032+ $ type ->isList ()->yes ()
10501033 && $ sizeType instanceof IntegerRangeType
10511034 && $ sizeType ->getMin () !== null
10521035 ) {
@@ -1083,6 +1066,18 @@ private function turnListIntoConstantArray(FuncCall $countFuncCall, Type $type,
10831066 return null ;
10841067 }
10851068
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+
10861081 private function specifyTypesForConstantBinaryExpression (
10871082 Expr $ exprNode ,
10881083 Type $ constantType ,
@@ -2112,11 +2107,9 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty
21122107 );
21132108 }
21142109
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 ;
21202113 }
21212114
21222115 if ($ context ->truthy ()) {
@@ -2129,7 +2122,8 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty
21292122 }
21302123
21312124 $ 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 ;
21332127 if ($ constArray !== null ) {
21342128 return $ funcTypes ->unionWith (
21352129 $ this ->create ($ unwrappedLeftExpr ->getArgs ()[0 ]->value , $ constArray , $ context , $ scope )->setRootExpr ($ expr ),
0 commit comments