@@ -984,75 +984,76 @@ private function specifyTypesForCountFuncCall(
984984 $ isNormalCount = (new ConstantIntegerType (COUNT_NORMAL ))->isSuperTypeOf ($ mode )->result ->or ($ type ->getIterableValueType ()->isArray ()->negate ());
985985 }
986986
987- if (!$ isNormalCount ->yes () || (!$ type ->isConstantArray ()->yes () && !$ type ->isList ()->yes ())) {
987+ $ isList = $ type ->isList ();
988+ if (
989+ !$ isNormalCount ->yes ()
990+ || (!$ type ->isConstantArray ()->yes () && !$ isList ->yes ())
991+ || $ type ->isIterableAtLeastOnce ()->no () // array{} cannot be used for further narrowing
992+ ) {
988993 return null ;
989994 }
990995
991996 $ resultTypes = [];
992- $ innerTypes = $ type instanceof UnionType ? $ type ->getTypes () : [$ type ];
993- foreach ($ innerTypes as $ innerType ) {
994- $ isSizeSuperTypeOfArraySize = $ sizeType ->isSuperTypeOf ($ innerType ->getArraySize ());
997+ foreach ($ type ->getArrays () as $ arrayType ) {
998+ $ isSizeSuperTypeOfArraySize = $ sizeType ->isSuperTypeOf ($ arrayType ->getArraySize ());
995999 if ($ isSizeSuperTypeOfArraySize ->no ()) {
9961000 continue ;
9971001 }
1002+
9981003 if ($ context ->falsey () && $ isSizeSuperTypeOfArraySize ->maybe ()) {
9991004 continue ;
10001005 }
10011006
10021007 if (
1003- $ innerType -> isList () ->yes ()
1008+ $ isList ->yes ()
10041009 && $ sizeType instanceof ConstantIntegerType
10051010 && $ sizeType ->getValue () < ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT
10061011 ) {
10071012 // turn optional offsets non-optional
10081013 $ valueTypesBuilder = ConstantArrayTypeBuilder::createEmpty ();
10091014 for ($ i = 0 ; $ i < $ sizeType ->getValue (); $ i ++) {
10101015 $ offsetType = new ConstantIntegerType ($ i );
1011- $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ innerType ->getOffsetValueType ($ offsetType ));
1016+ $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ arrayType ->getOffsetValueType ($ offsetType ));
10121017 }
10131018 $ resultTypes [] = $ valueTypesBuilder ->getArray ();
10141019 continue ;
10151020 }
10161021
10171022 if (
1018- $ innerType -> isList () ->yes ()
1023+ $ isList ->yes ()
10191024 && $ sizeType instanceof IntegerRangeType
10201025 && $ sizeType ->getMin () !== null
10211026 ) {
10221027 // turn optional offsets non-optional
10231028 $ valueTypesBuilder = ConstantArrayTypeBuilder::createEmpty ();
10241029 for ($ i = 0 ; $ i < $ sizeType ->getMin (); $ i ++) {
10251030 $ offsetType = new ConstantIntegerType ($ i );
1026- $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ innerType ->getOffsetValueType ($ offsetType ));
1031+ $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ arrayType ->getOffsetValueType ($ offsetType ));
10271032 }
10281033 if ($ sizeType ->getMax () !== null ) {
10291034 for ($ i = $ sizeType ->getMin (); $ i < $ sizeType ->getMax (); $ i ++) {
10301035 $ offsetType = new ConstantIntegerType ($ i );
1031- $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ innerType ->getOffsetValueType ($ offsetType ), true );
1036+ $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ arrayType ->getOffsetValueType ($ offsetType ), true );
10321037 }
1033- } elseif ($ innerType ->isConstantArray ()->yes ()) {
1038+ } elseif ($ arrayType ->isConstantArray ()->yes ()) {
10341039 for ($ i = $ sizeType ->getMin ();; $ i ++) {
10351040 $ offsetType = new ConstantIntegerType ($ i );
1036- $ hasOffset = $ innerType ->hasOffsetValueType ($ offsetType );
1041+ $ hasOffset = $ arrayType ->hasOffsetValueType ($ offsetType );
10371042 if ($ hasOffset ->no ()) {
10381043 break ;
10391044 }
1040- $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ innerType ->getOffsetValueType ($ offsetType ), !$ hasOffset ->yes ());
1045+ $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ arrayType ->getOffsetValueType ($ offsetType ), !$ hasOffset ->yes ());
10411046 }
10421047 } else {
1043- $ resultTypes [] = TypeCombinator::intersect ($ innerType , new NonEmptyArrayType ());
1048+ $ resultTypes [] = TypeCombinator::intersect ($ arrayType , new NonEmptyArrayType ());
10441049 continue ;
10451050 }
10461051
10471052 $ resultTypes [] = $ valueTypesBuilder ->getArray ();
10481053 continue ;
10491054 }
10501055
1051- if (!$ context ->truthy ()) {
1052- continue ;
1053- }
1054-
1055- $ resultTypes [] = $ innerType ;
1056+ $ resultTypes [] = $ arrayType ;
10561057 }
10571058
10581059 return $ this ->create ($ countFuncCall ->getArgs ()[0 ]->value , TypeCombinator::union (...$ resultTypes ), $ context , $ scope )->setRootExpr ($ rootExpr );
0 commit comments