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