@@ -188,58 +188,12 @@ public static function union(Type ...$types): Type
188188 }
189189 }
190190
191- // Fast path for N>2: strip implicit NeverTypes and short-circuit on mixed
192- if ($ typesCount > 2 ) {
193- $ neverCount = 0 ;
194- $ hasUnionOrBenevolent = false ;
195- for ($ i = 0 ; $ i < $ typesCount ; $ i ++) {
196- $ t = $ types [$ i ];
197- if (
198- $ t instanceof MixedType
199- && !$ t ->isExplicitMixed ()
200- && !$ t instanceof TemplateMixedType
201- && $ t ->getSubtractedType () === null
202- ) {
203- return $ t ;
204- }
205- if ($ t instanceof NeverType && !$ t ->isExplicit ()) {
206- $ neverCount ++;
207- } elseif ($ t instanceof UnionType && !$ t instanceof TemplateType) {
208- $ hasUnionOrBenevolent = true ;
209- }
210- }
211-
212- if ($ neverCount > 0 && !$ hasUnionOrBenevolent ) {
213- if ($ neverCount === $ typesCount ) {
214- return new NeverType ();
215- }
216-
217- $ filtered = [];
218- for ($ i = 0 ; $ i < $ typesCount ; $ i ++) {
219- if ($ types [$ i ] instanceof NeverType && !$ types [$ i ]->isExplicit ()) {
220- continue ;
221- }
222-
223- $ filtered [] = $ types [$ i ];
224- }
225- $ filteredCount = count ($ filtered );
226-
227- if ($ filteredCount === 1 && !$ filtered [0 ]->isArray ()->yes ()) {
228- return $ filtered [0 ];
229- }
230- if ($ filteredCount === 2 ) {
231- return self ::union ($ filtered [0 ], $ filtered [1 ]);
232- }
233- $ types = $ filtered ;
234- $ typesCount = $ filteredCount ;
235- }
236- }
237-
238191 $ alreadyNormalized = [];
239192 $ alreadyNormalizedCounter = 0 ;
240193
241194 $ benevolentTypes = [];
242195 $ benevolentUnionObject = null ;
196+ $ neverCount = 0 ;
243197 // transform A | (B | C) to A | B | C
244198 for ($ i = 0 ; $ i < $ typesCount ; $ i ++) {
245199 if (
@@ -251,8 +205,7 @@ public static function union(Type ...$types): Type
251205 return $ types [$ i ];
252206 }
253207 if ($ types [$ i ] instanceof NeverType && !$ types [$ i ]->isExplicit ()) {
254- array_splice ($ types , $ i --, 1 );
255- $ typesCount --;
208+ $ neverCount ++;
256209 continue ;
257210 }
258211 if ($ types [$ i ] instanceof BenevolentUnionType) {
@@ -283,6 +236,33 @@ public static function union(Type ...$types): Type
283236 $ typesCount += count ($ typesInner ) - 1 ;
284237 }
285238
239+ // Bulk-remove implicit NeverTypes (skipped during the loop above)
240+ if ($ neverCount > 0 ) {
241+ if ($ neverCount === $ typesCount ) {
242+ return new NeverType ();
243+ }
244+
245+ $ filtered = [];
246+ for ($ i = 0 ; $ i < $ typesCount ; $ i ++) {
247+ if ($ types [$ i ] instanceof NeverType && !$ types [$ i ]->isExplicit ()) {
248+ continue ;
249+ }
250+ $ filtered [] = $ types [$ i ];
251+ }
252+ $ types = $ filtered ;
253+ $ typesCount = count ($ types );
254+
255+ if ($ typesCount === 0 ) {
256+ return new NeverType ();
257+ }
258+ if ($ typesCount === 1 && !$ types [0 ]->isArray ()->yes ()) {
259+ return $ types [0 ];
260+ }
261+ if ($ typesCount === 2 ) {
262+ return self ::union ($ types [0 ], $ types [1 ]);
263+ }
264+ }
265+
286266 if ($ typesCount === 0 ) {
287267 return new NeverType ();
288268 }
0 commit comments