@@ -41,6 +41,8 @@ final class ConstantArrayTypeBuilder
4141
4242 private bool $ oversized = false ;
4343
44+ private TrinaryLogic $ isNonEmpty ;
45+
4446 /**
4547 * @param list<Type> $keyTypes
4648 * @param array<int, Type> $valueTypes
@@ -55,6 +57,7 @@ private function __construct(
5557 private TrinaryLogic $ isList ,
5658 )
5759 {
60+ $ this ->isNonEmpty = TrinaryLogic::createNo ();
5861 }
5962
6063 public static function createEmpty (): self
@@ -71,6 +74,7 @@ public static function createFromConstantArray(ConstantArrayType $startArrayType
7174 $ startArrayType ->getOptionalKeys (),
7275 $ startArrayType ->isList (),
7376 );
77+ $ builder ->isNonEmpty = $ startArrayType ->isIterableAtLeastOnce ();
7478
7579 if (count ($ startArrayType ->getKeyTypes ()) > self ::ARRAY_COUNT_LIMIT ) {
7680 $ builder ->degradeToGeneralArray (true );
@@ -89,6 +93,10 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $opt
8993 return ;
9094 }
9195
96+ if (!$ optional ) {
97+ $ this ->isNonEmpty = TrinaryLogic::createYes ();
98+ }
99+
92100 if (!$ this ->degradeToGeneralArray ) {
93101 if (
94102 $ valueType instanceof ClosureType
@@ -388,7 +396,11 @@ public function getArray(): Type
388396 if (!$ this ->degradeToGeneralArray ) {
389397 /** @var list<ConstantIntegerType|ConstantStringType> $keyTypes */
390398 $ keyTypes = $ this ->keyTypes ;
391- return new ConstantArrayType ($ keyTypes , $ this ->valueTypes , $ this ->nextAutoIndexes , $ this ->optionalKeys , $ this ->isList );
399+ $ array = new ConstantArrayType ($ keyTypes , $ this ->valueTypes , $ this ->nextAutoIndexes , $ this ->optionalKeys , $ this ->isList );
400+ if ($ this ->isNonEmpty ->yes () && !$ array ->isIterableAtLeastOnce ()->yes ()) {
401+ return TypeCombinator::intersect ($ array , new NonEmptyArrayType ());
402+ }
403+ return $ array ;
392404 }
393405
394406 if ($ this ->degradeClosures === true ) {
@@ -410,7 +422,7 @@ public function getArray(): Type
410422 );
411423
412424 $ types = [];
413- if (count ($ this ->optionalKeys ) < $ keyTypesCount ) {
425+ if ($ this -> isNonEmpty -> yes () || count ($ this ->optionalKeys ) < $ keyTypesCount ) {
414426 $ types [] = new NonEmptyArrayType ();
415427 }
416428
0 commit comments