@@ -246,11 +246,16 @@ public function specifyTypesInCondition(
246246 ) {
247247 $ argType = $ scope ->getType ($ expr ->right ->getArgs ()[0 ]->value );
248248
249- if ($ argType instanceof UnionType && $ leftType instanceof ConstantIntegerType) {
250- if ($ orEqual ) {
251- $ sizeType = IntegerRangeType::createAllGreaterThanOrEqualTo ($ leftType ->getValue ());
252- } else {
253- $ sizeType = IntegerRangeType::createAllGreaterThan ($ leftType ->getValue ());
249+ if ($ argType instanceof UnionType) {
250+ $ sizeType = null ;
251+ if ($ leftType instanceof ConstantIntegerType) {
252+ if ($ orEqual ) {
253+ $ sizeType = IntegerRangeType::createAllGreaterThanOrEqualTo ($ leftType ->getValue ());
254+ } else {
255+ $ sizeType = IntegerRangeType::createAllGreaterThan ($ leftType ->getValue ());
256+ }
257+ } elseif ($ leftType instanceof IntegerRangeType) {
258+ $ sizeType = $ leftType ;
254259 }
255260
256261 $ narrowed = $ this ->narrowUnionByArraySize ($ expr ->right , $ argType , $ sizeType , $ context , $ scope , $ rootExpr );
@@ -943,8 +948,12 @@ public function specifyTypesInCondition(
943948 return new SpecifiedTypes ([], [], false , [], $ rootExpr );
944949 }
945950
946- private function narrowUnionByArraySize (FuncCall $ countFuncCall , UnionType $ argType , Type $ sizeType , TypeSpecifierContext $ context , Scope $ scope , ?Expr $ rootExpr ): ?SpecifiedTypes
951+ private function narrowUnionByArraySize (FuncCall $ countFuncCall , UnionType $ argType , ? Type $ sizeType , TypeSpecifierContext $ context , Scope $ scope , ?Expr $ rootExpr ): ?SpecifiedTypes
947952 {
953+ if ($ sizeType === null ) {
954+ return null ;
955+ }
956+
948957 if (count ($ countFuncCall ->getArgs ()) === 1 ) {
949958 $ isNormalCount = TrinaryLogic::createYes ();
950959 } else {
@@ -1011,6 +1020,37 @@ private function turnListIntoConstantArray(FuncCall $countFuncCall, Type $type,
10111020 return $ valueTypesBuilder ->getArray ();
10121021 }
10131022
1023+ if (
1024+ $ isNormalCount ->yes ()
1025+ && $ type ->isList ()->yes ()
1026+ && $ sizeType instanceof IntegerRangeType
1027+ && $ sizeType ->getMin () !== null
1028+ ) {
1029+ // turn optional offsets non-optional
1030+ $ valueTypesBuilder = ConstantArrayTypeBuilder::createEmpty ();
1031+ for ($ i = 0 ; $ i < $ sizeType ->getMin (); $ i ++) {
1032+ $ offsetType = new ConstantIntegerType ($ i );
1033+ $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ type ->getOffsetValueType ($ offsetType ));
1034+ }
1035+ if ($ sizeType ->getMax () !== null ) {
1036+ for ($ i = $ sizeType ->getMin (); $ i < $ sizeType ->getMax (); $ i ++) {
1037+ $ offsetType = new ConstantIntegerType ($ i );
1038+ $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ type ->getOffsetValueType ($ offsetType ), true );
1039+ }
1040+ } else {
1041+ for ($ i = $ sizeType ->getMin ();; $ i ++) {
1042+ $ offsetType = new ConstantIntegerType ($ i );
1043+ $ hasOffset = $ type ->hasOffsetValueType ($ offsetType );
1044+ if ($ hasOffset ->no ()) {
1045+ break ;
1046+ }
1047+ $ valueTypesBuilder ->setOffsetValueType ($ offsetType , $ type ->getOffsetValueType ($ offsetType ), !$ hasOffset ->yes ());
1048+ }
1049+
1050+ }
1051+ return $ valueTypesBuilder ->getArray ();
1052+ }
1053+
10141054 return null ;
10151055 }
10161056
0 commit comments