@@ -277,22 +277,20 @@ public function specifyTypesInCondition(
277277 ) {
278278 $ argType = $ scope ->getType ($ expr ->right ->getArgs ()[0 ]->value );
279279
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 ());
290286 }
287+ } elseif ($ leftType instanceof IntegerRangeType) {
288+ $ sizeType = $ leftType ;
289+ }
291290
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 );
296294 }
297295
298296 if (
@@ -1010,66 +1008,64 @@ public function specifyTypesInCondition(
10101008 return new SpecifiedTypes ([], [], false , [], $ rootExpr );
10111009 }
10121010
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
10141012 {
10151013 if ($ sizeType === null ) {
10161014 return null ;
10171015 }
10181016
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-
10261017 if (
1027- $ isNormalCount ->yes ()
1028- && $ argType ->isConstantArray ()->yes ()
1018+ $ this -> isNormalCount ( $ countFuncCall , $ scope ) ->yes ()
1019+ && $ type ->isConstantArray ()->yes ()
10291020 ) {
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 ();
10331027 $ isSize = $ sizeType ->isSuperTypeOf ($ arraySize );
10341028 if ($ context ->truthy ()) {
10351029 if ($ isSize ->no ()) {
1036- continue ;
1030+ return new NeverType () ;
10371031 }
10381032
1039- $ constArray = $ this ->turnListIntoConstantArray ($ countFuncCall , $ innerType , $ sizeType, $ scope );
1033+ $ constArray = $ this ->turnListIntoConstantArray ($ type , $ sizeType );
10401034 if ($ constArray !== null ) {
1041- $ innerType = $ constArray ;
1035+ $ type = $ constArray ;
10421036 }
10431037 }
10441038 if ($ context ->falsey ()) {
10451039 if (!$ isSize ->yes ()) {
1046- continue ;
1040+ return new NeverType () ;
10471041 }
10481042 }
10491043
1050- $ result [] = $ innerType ;
1051- }
1044+ return $ type ;
1045+ });
10521046
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 );
10541048 }
10551049
10561050 return null ;
10571051 }
10581052
1059- private function turnListIntoConstantArray (FuncCall $ countFuncCall , Type $ type , Type $ sizeType , Scope $ scope ): ? Type
1053+ private function isNormalCount (FuncCall $ countFuncCall , Scope $ scope ): TrinaryLogic
10601054 {
10611055 $ argType = $ scope ->getType ($ countFuncCall ->getArgs ()[0 ]->value );
10621056
10631057 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 ();
10681059 }
1060+ $ mode = $ scope ->getType ($ countFuncCall ->getArgs ()[1 ]->value );
1061+
1062+ return (new ConstantIntegerType (COUNT_NORMAL ))->isSuperTypeOf ($ mode )->or ($ argType ->getIterableValueType ()->isArray ()->negate ());
1063+ }
10691064
1065+ private function turnListIntoConstantArray (Type $ type , Type $ sizeType ): ?Type
1066+ {
10701067 if (
1071- $ isNormalCount ->yes ()
1072- && $ type ->isList ()->yes ()
1068+ $ type ->isList ()->yes ()
10731069 && $ sizeType instanceof ConstantIntegerType
10741070 && $ sizeType ->getValue () < ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT
10751071 ) {
@@ -1083,8 +1079,7 @@ private function turnListIntoConstantArray(FuncCall $countFuncCall, Type $type,
10831079 }
10841080
10851081 if (
1086- $ isNormalCount ->yes ()
1087- && $ type ->isList ()->yes ()
1082+ $ type ->isList ()->yes ()
10881083 && $ sizeType instanceof IntegerRangeType
10891084 && $ sizeType ->getMin () !== null
10901085 ) {
@@ -2171,11 +2166,9 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty
21712166 );
21722167 }
21732168
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 ;
21792172 }
21802173
21812174 if ($ context ->truthy ()) {
@@ -2188,7 +2181,8 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty
21882181 }
21892182
21902183 $ 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 ;
21922186 if ($ constArray !== null ) {
21932187 return $ funcTypes ->unionWith (
21942188 $ this ->create ($ unwrappedLeftExpr ->getArgs ()[0 ]->value , $ constArray , $ context , false , $ scope , $ rootExpr ),
0 commit comments