@@ -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+ ) {
10651070return 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 ());
10721076if ($ isSizeSuperTypeOfArraySize ->no ()) {
10731077continue ;
10741078}
1079+
10751080if ($ context ->falsey () && $ isSizeSuperTypeOfArraySize ->maybe ()) {
10761081continue ;
10771082}
10781083
10791084if (
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 ();
10861091for ($ 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 ();
10911096continue ;
10921097}
10931098
10941099if (
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 ();
11011106for ($ 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}
11051110if ($ sizeType ->getMax () !== null ) {
11061111for ($ 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 ()) {
11111116for ($ i = $ sizeType ->getMin ();; $ i ++) {
11121117$ offsetType = new ConstantIntegerType ($ i );
1113- $ hasOffset = $ innerType ->hasOffsetValueType ($ offsetType );
1118+ $ hasOffset = $ arrayType ->hasOffsetValueType ($ offsetType );
11141119if ($ hasOffset ->no ()) {
11151120break ;
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 ());
11211126continue ;
11221127}
11231128
11241129$ resultTypes [] = $ valueTypesBuilder ->getArray ();
11251130continue ;
11261131}
11271132
1128- if (!$ context ->truthy ()) {
1129- continue ;
1130- }
1131-
1132- $ resultTypes [] = $ innerType ;
1133+ $ resultTypes [] = $ arrayType ;
11331134}
11341135
11351136return $ this ->create ($ countFuncCall ->getArgs ()[0 ]->value , TypeCombinator::union (...$ resultTypes ), $ context , $ scope )->setRootExpr ($ rootExpr );
0 commit comments