@@ -987,75 +987,76 @@ private function specifyTypesForCountFuncCall(
987987 $ isNormalCount = (new ConstantIntegerType (COUNT_NORMAL ))->isSuperTypeOf ($ mode )->result ->or ($ type ->getIterableValueType ()->isArray ()->negate ());
988988 }
989989
990- if (!$ isNormalCount ->yes () || (!$ type ->isConstantArray ()->yes () && !$ type ->isList ()->yes ())) {
990+ $ isList = $ type ->isList ();
991+ if (
992+ !$ isNormalCount ->yes ()
993+ || (!$ type ->isConstantArray ()->yes () && !$ isList ->yes ())
994+ || $ type ->isIterableAtLeastOnce ()->no () // array{} cannot be used for further narrowing
995+ ) {
991996 return null ;
992997 }
993998
994999 $ resultTypes = [];
995- $ innerTypes = $ type instanceof UnionType ? $ type ->getTypes () : [$ type ];
996- foreach ($ innerTypes as $ innerType ) {
997- $ isSizeSuperTypeOfArraySize = $ sizeType ->isSuperTypeOf ($ innerType ->getArraySize ());
1000+ foreach ($ type ->getArrays () as $ arrayType ) {
1001+ $ isSizeSuperTypeOfArraySize = $ sizeType ->isSuperTypeOf ($ arrayType ->getArraySize ());
9981002 if ($ isSizeSuperTypeOfArraySize ->no ()) {
9991003 continue ;
10001004 }
1005+
10011006 if ($ context ->falsey () && $ isSizeSuperTypeOfArraySize ->maybe ()) {
10021007 continue ;
10031008 }
10041009
10051010 if (
1006- $ innerType -> isList () ->yes ()
1011+ $ isList ->yes ()
10071012 && $ sizeType instanceof ConstantIntegerType
10081013 && $ sizeType ->getValue () < ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT
10091014 ) {
10101015 // turn optional offsets non-optional
10111016 $ valueTypesBuilder = ConstantArrayTypeBuilder::createEmpty ();
10121017 for ($ i = 0 ; $ i < $ sizeType ->getValue (); $ i ++) {
10131018 $ offsetType = new ConstantIntegerType ($ i );
1014- $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ innerType ->getOffsetValueType ($ offsetType ));
1019+ $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ arrayType ->getOffsetValueType ($ offsetType ));
10151020 }
10161021 $ resultTypes [] = $ valueTypesBuilder ->getArray ();
10171022 continue ;
10181023 }
10191024
10201025 if (
1021- $ innerType -> isList () ->yes ()
1026+ $ isList ->yes ()
10221027 && $ sizeType instanceof IntegerRangeType
10231028 && $ sizeType ->getMin () !== null
10241029 ) {
10251030 // turn optional offsets non-optional
10261031 $ valueTypesBuilder = ConstantArrayTypeBuilder::createEmpty ();
10271032 for ($ i = 0 ; $ i < $ sizeType ->getMin (); $ i ++) {
10281033 $ offsetType = new ConstantIntegerType ($ i );
1029- $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ innerType ->getOffsetValueType ($ offsetType ));
1034+ $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ arrayType ->getOffsetValueType ($ offsetType ));
10301035 }
10311036 if ($ sizeType ->getMax () !== null ) {
10321037 for ($ i = $ sizeType ->getMin (); $ i < $ sizeType ->getMax (); $ i ++) {
10331038 $ offsetType = new ConstantIntegerType ($ i );
1034- $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ innerType ->getOffsetValueType ($ offsetType ), true );
1039+ $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ arrayType ->getOffsetValueType ($ offsetType ), true );
10351040 }
1036- } elseif ($ innerType ->isConstantArray ()->yes ()) {
1041+ } elseif ($ arrayType ->isConstantArray ()->yes ()) {
10371042 for ($ i = $ sizeType ->getMin ();; $ i ++) {
10381043 $ offsetType = new ConstantIntegerType ($ i );
1039- $ hasOffset = $ innerType ->hasOffsetValueType ($ offsetType );
1044+ $ hasOffset = $ arrayType ->hasOffsetValueType ($ offsetType );
10401045 if ($ hasOffset ->no ()) {
10411046 break ;
10421047 }
1043- $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ innerType ->getOffsetValueType ($ offsetType ), !$ hasOffset ->yes ());
1048+ $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ arrayType ->getOffsetValueType ($ offsetType ), !$ hasOffset ->yes ());
10441049 }
10451050 } else {
1046- $ resultTypes [] = TypeCombinator::intersect ($ innerType , new NonEmptyArrayType ());
1051+ $ resultTypes [] = TypeCombinator::intersect ($ arrayType , new NonEmptyArrayType ());
10471052 continue ;
10481053 }
10491054
10501055 $ resultTypes [] = $ valueTypesBuilder ->getArray ();
10511056 continue ;
10521057 }
10531058
1054- if (!$ context ->truthy ()) {
1055- continue ;
1056- }
1057-
1058- $ resultTypes [] = $ innerType ;
1059+ $ resultTypes [] = $ arrayType ;
10591060 }
10601061
10611062 return $ this ->create ($ countFuncCall ->getArgs ()[0 ]->value , TypeCombinator::union (...$ resultTypes ), $ context , $ scope )->setRootExpr ($ rootExpr );
0 commit comments