@@ -1061,75 +1061,76 @@ private function specifyTypesForCountFuncCall(
10611061 $ isNormalCount = (new ConstantIntegerType (COUNT_NORMAL ))->isSuperTypeOf ($ mode )->result ->or ($ type ->getIterableValueType ()->isArray ()->negate ());
10621062 }
10631063
1064- if (!$ isNormalCount ->yes () || (!$ type ->isConstantArray ()->yes () && !$ type ->isList ()->yes ())) {
1064+ $ isList = $ type ->isList ();
1065+ if (
1066+ !$ isNormalCount ->yes ()
1067+ || (!$ type ->isConstantArray ()->yes () && !$ isList ->yes ())
1068+ || $ type ->isIterableAtLeastOnce ()->no () // array{} cannot be used for further narrowing
1069+ ) {
10651070 return null ;
10661071 }
10671072
10681073 $ resultTypes = [];
1069- $ innerTypes = $ type instanceof UnionType ? $ type ->getTypes () : [$ type ];
1070- foreach ($ innerTypes as $ innerType ) {
1071- $ isSizeSuperTypeOfArraySize = $ sizeType ->isSuperTypeOf ($ innerType ->getArraySize ());
1074+ foreach ($ type ->getArrays () as $ arrayType ) {
1075+ $ isSizeSuperTypeOfArraySize = $ sizeType ->isSuperTypeOf ($ arrayType ->getArraySize ());
10721076 if ($ isSizeSuperTypeOfArraySize ->no ()) {
10731077 continue ;
10741078 }
1079+
10751080 if ($ context ->falsey () && $ isSizeSuperTypeOfArraySize ->maybe ()) {
10761081 continue ;
10771082 }
10781083
10791084 if (
1080- $ innerType -> isList () ->yes ()
1085+ $ isList ->yes ()
10811086 && $ sizeType instanceof ConstantIntegerType
10821087 && $ sizeType ->getValue () < ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT
10831088 ) {
10841089 // turn optional offsets non-optional
10851090 $ valueTypesBuilder = ConstantArrayTypeBuilder::createEmpty ();
10861091 for ($ i = 0 ; $ i < $ sizeType ->getValue (); $ i ++) {
10871092 $ offsetType = new ConstantIntegerType ($ i );
1088- $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ innerType ->getOffsetValueType ($ offsetType ));
1093+ $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ arrayType ->getOffsetValueType ($ offsetType ));
10891094 }
10901095 $ resultTypes [] = $ valueTypesBuilder ->getArray ();
10911096 continue ;
10921097 }
10931098
10941099 if (
1095- $ innerType -> isList () ->yes ()
1100+ $ isList ->yes ()
10961101 && $ sizeType instanceof IntegerRangeType
10971102 && $ sizeType ->getMin () !== null
10981103 ) {
10991104 // turn optional offsets non-optional
11001105 $ valueTypesBuilder = ConstantArrayTypeBuilder::createEmpty ();
11011106 for ($ i = 0 ; $ i < $ sizeType ->getMin (); $ i ++) {
11021107 $ offsetType = new ConstantIntegerType ($ i );
1103- $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ innerType ->getOffsetValueType ($ offsetType ));
1108+ $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ arrayType ->getOffsetValueType ($ offsetType ));
11041109 }
11051110 if ($ sizeType ->getMax () !== null ) {
11061111 for ($ i = $ sizeType ->getMin (); $ i < $ sizeType ->getMax (); $ i ++) {
11071112 $ offsetType = new ConstantIntegerType ($ i );
1108- $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ innerType ->getOffsetValueType ($ offsetType ), true );
1113+ $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ arrayType ->getOffsetValueType ($ offsetType ), true );
11091114 }
1110- } elseif ($ innerType ->isConstantArray ()->yes ()) {
1115+ } elseif ($ arrayType ->isConstantArray ()->yes ()) {
11111116 for ($ i = $ sizeType ->getMin ();; $ i ++) {
11121117 $ offsetType = new ConstantIntegerType ($ i );
1113- $ hasOffset = $ innerType ->hasOffsetValueType ($ offsetType );
1118+ $ hasOffset = $ arrayType ->hasOffsetValueType ($ offsetType );
11141119 if ($ hasOffset ->no ()) {
11151120 break ;
11161121 }
1117- $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ innerType ->getOffsetValueType ($ offsetType ), !$ hasOffset ->yes ());
1122+ $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ arrayType ->getOffsetValueType ($ offsetType ), !$ hasOffset ->yes ());
11181123 }
11191124 } else {
1120- $ resultTypes [] = TypeCombinator::intersect ($ innerType , new NonEmptyArrayType ());
1125+ $ resultTypes [] = TypeCombinator::intersect ($ arrayType , new NonEmptyArrayType ());
11211126 continue ;
11221127 }
11231128
11241129 $ resultTypes [] = $ valueTypesBuilder ->getArray ();
11251130 continue ;
11261131 }
11271132
1128- if (!$ context ->truthy ()) {
1129- continue ;
1130- }
1131-
1132- $ resultTypes [] = $ innerType ;
1133+ $ resultTypes [] = $ arrayType ;
11331134 }
11341135
11351136 return $ this ->create ($ countFuncCall ->getArgs ()[0 ]->value , TypeCombinator::union (...$ resultTypes ), $ context , $ scope )->setRootExpr ($ rootExpr );
0 commit comments