@@ -44,7 +44,7 @@ final class ConstantArrayTypeBuilder
4444 /**
4545 * @param list<Type> $keyTypes
4646 * @param array<int, Type> $valueTypes
47- * @param non-empty- list<int> $nextAutoIndexes
47+ * @param list<int> $nextAutoIndexes
4848 * @param array<int> $optionalKeys
4949 */
5050 private function __construct (
@@ -85,6 +85,10 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $opt
8585 $ offsetType = $ offsetType ->toArrayKey ();
8686 }
8787
88+ if ($ offsetType === null && count ($ this ->nextAutoIndexes ) === 0 ) {
89+ return ;
90+ }
91+
8892 if (!$ this ->degradeToGeneralArray ) {
8993 if (
9094 $ valueType instanceof ClosureType
@@ -108,6 +112,10 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $opt
108112 }
109113
110114 if ($ offsetType === null ) {
115+ if (count ($ this ->nextAutoIndexes ) === 0 ) {
116+ return ;
117+ }
118+
111119 $ newAutoIndexes = $ optional ? $ this ->nextAutoIndexes : [];
112120 $ hasOptional = false ;
113121 foreach ($ this ->keyTypes as $ i => $ keyType ) {
@@ -127,11 +135,10 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $opt
127135
128136 /** @var int|float $newAutoIndex */
129137 $ newAutoIndex = $ keyType ->getValue () + 1 ;
130- if (is_float ($ newAutoIndex )) {
131- $ newAutoIndex = $ keyType -> getValue () ;
138+ if (! is_float ($ newAutoIndex )) {
139+ $ newAutoIndexes [] = $ newAutoIndex ;
132140 }
133141
134- $ newAutoIndexes [] = $ newAutoIndex ;
135142 $ hasOptional = true ;
136143 }
137144
@@ -142,11 +149,10 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $opt
142149
143150 /** @var int|float $newAutoIndex */
144151 $ newAutoIndex = $ max + 1 ;
145- if (is_float ($ newAutoIndex )) {
146- $ newAutoIndex = $ max ;
152+ if (! is_float ($ newAutoIndex )) {
153+ $ newAutoIndexes [] = $ newAutoIndex ;
147154 }
148155
149- $ newAutoIndexes [] = $ newAutoIndex ;
150156 $ this ->nextAutoIndexes = array_values (array_unique ($ newAutoIndexes ));
151157
152158 if ($ optional || $ hasOptional ) {
@@ -180,11 +186,7 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $opt
180186 if (!$ optional ) {
181187 $ this ->optionalKeys = array_values (array_filter ($ this ->optionalKeys , static fn (int $ index ): bool => $ index !== $ i ));
182188 if ($ keyType instanceof ConstantIntegerType) {
183- $ nextAutoIndexes = array_values (array_filter ($ this ->nextAutoIndexes , static fn (int $ index ) => $ index > $ keyType ->getValue ()));
184- if (count ($ nextAutoIndexes ) === 0 ) {
185- throw new ShouldNotHappenException ();
186- }
187- $ this ->nextAutoIndexes = $ nextAutoIndexes ;
189+ $ this ->nextAutoIndexes = array_values (array_filter ($ this ->nextAutoIndexes , static fn (int $ index ) => $ index > $ keyType ->getValue ()));
188190 }
189191 }
190192 return ;
@@ -194,33 +196,38 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $opt
194196 $ this ->valueTypes [] = $ valueType ;
195197
196198 if ($ offsetType instanceof ConstantIntegerType) {
197- $ min = min ($ this ->nextAutoIndexes );
198- $ max = max ($ this ->nextAutoIndexes );
199- $ offsetValue = $ offsetType ->getValue ();
200- if ($ offsetValue >= 0 ) {
201- if ($ offsetValue > $ min ) {
202- if ($ offsetValue <= $ max ) {
203- $ this ->isList = $ this ->isList ->and (TrinaryLogic::createMaybe ());
199+ if (count ($ this ->nextAutoIndexes ) > 0 ) {
200+ $ min = min ($ this ->nextAutoIndexes );
201+ $ max = max ($ this ->nextAutoIndexes );
202+ $ offsetValue = $ offsetType ->getValue ();
203+ if ($ offsetValue >= 0 ) {
204+ if ($ offsetValue > $ min ) {
205+ if ($ offsetValue <= $ max ) {
206+ $ this ->isList = $ this ->isList ->and (TrinaryLogic::createMaybe ());
207+ } else {
208+ $ this ->isList = TrinaryLogic::createNo ();
209+ }
210+ }
211+ } else {
212+ $ this ->isList = TrinaryLogic::createNo ();
213+ }
214+
215+ if ($ offsetValue >= $ max ) {
216+ /** @var int|float $newAutoIndex */
217+ $ newAutoIndex = $ offsetValue + 1 ;
218+ if (is_float ($ newAutoIndex )) {
219+ if (!$ optional ) {
220+ $ this ->nextAutoIndexes = [];
221+ }
222+ } elseif (!$ optional ) {
223+ $ this ->nextAutoIndexes = [$ newAutoIndex ];
204224 } else {
205- $ this ->isList = TrinaryLogic:: createNo () ;
225+ $ this ->nextAutoIndexes [] = $ newAutoIndex ;
206226 }
207227 }
208228 } else {
209229 $ this ->isList = TrinaryLogic::createNo ();
210230 }
211-
212- if ($ offsetValue >= $ max ) {
213- /** @var int|float $newAutoIndex */
214- $ newAutoIndex = $ offsetValue + 1 ;
215- if (is_float ($ newAutoIndex )) {
216- $ newAutoIndex = $ max ;
217- }
218- if (!$ optional ) {
219- $ this ->nextAutoIndexes = [$ newAutoIndex ];
220- } else {
221- $ this ->nextAutoIndexes [] = $ newAutoIndex ;
222- }
223- }
224231 } else {
225232 $ this ->isList = TrinaryLogic::createNo ();
226233 }
@@ -300,6 +307,10 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $opt
300307 continue ;
301308 }
302309
310+ if (count ($ this ->nextAutoIndexes ) === 0 ) {
311+ continue ;
312+ }
313+
303314 $ max = max ($ this ->nextAutoIndexes );
304315 $ offsetValue = $ scalarType ->getValue ();
305316 if ($ offsetValue < $ max ) {
@@ -309,7 +320,7 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $opt
309320 /** @var int|float $newAutoIndex */
310321 $ newAutoIndex = $ offsetValue + 1 ;
311322 if (is_float ($ newAutoIndex )) {
312- $ newAutoIndex = $ max ;
323+ continue ;
313324 }
314325 $ this ->nextAutoIndexes [] = $ newAutoIndex ;
315326 }
0 commit comments