@@ -38,6 +38,8 @@ import java.lang.ref.WeakReference
38
38
import compiletime .uninitialized
39
39
import cc .{CapturingType , CaptureSet , derivedCapturingType , isBoxedCapturing , EventuallyCapturingType , boxedUnlessFun }
40
40
import CaptureSet .{CompareResult , IdempotentCaptRefMap , IdentityCaptRefMap }
41
+ import scala .collection .mutable .ListBuffer
42
+ import dotty .tools .dotc .util ._
41
43
42
44
import scala .annotation .internal .sharable
43
45
import scala .annotation .threadUnsafe
@@ -3485,40 +3487,52 @@ object Types {
3485
3487
3486
3488
/** Returns the set of non-union (leaf) types composing this union tree with Nothing types
3487
3489
* absorbed by other types, if present. For example:<br>
3488
- * `(A | B | C | B | (A & (B | C)) | Nothing)` returns `Set(A, B, C, (A & (B | C)))`.
3489
- */
3490
- private def gatherTreeUniqueMembersAbsorbingNothingTypes (using Context ): Set [Type ] = {
3491
- (tp1, tp2) match
3492
- case (l : OrType , r : OrType ) =>
3493
- l.gatherTreeUniqueMembersAbsorbingNothingTypes ++ r.gatherTreeUniqueMembersAbsorbingNothingTypes
3494
- case (l : OrType , r) =>
3495
- if r.isNothingType
3496
- then l.gatherTreeUniqueMembersAbsorbingNothingTypes
3497
- else l.gatherTreeUniqueMembersAbsorbingNothingTypes + r
3498
- case (l, r : OrType ) =>
3499
- if l.isNothingType
3500
- then r.gatherTreeUniqueMembersAbsorbingNothingTypes
3501
- else r.gatherTreeUniqueMembersAbsorbingNothingTypes + l
3502
- case (l, r) =>
3503
- if r.isNothingType then Set (l)
3504
- else if l.isNothingType then Set (r)
3505
- else Set (l, r)
3506
- }
3507
-
3508
- /** Returns an equivalent union tree without repeated members and with Nothing types absorbed
3509
- * by other types, if present. Weaker than LUB.
3490
+ * `(A | B | C | B | (A & (B | C)) | Nothing)` returns `{A, B, C, (A & (B | C))}`.
3491
+ */
3492
+ private def gatherTreeUniqueMembersAbsorbingNothingTypes (using Context ): MutableSet [Type ] = {
3493
+
3494
+ var trees = List (this )
3495
+ val uniqueTreeMembers = new EqLinkedHashSet [Type ]
3496
+
3497
+ while (trees.nonEmpty) {
3498
+ trees match {
3499
+ case head :: tail =>
3500
+ head match {
3501
+ case OrType (l : OrType , r : OrType ) =>
3502
+ trees = l :: r :: tail
3503
+ case OrType (l, r : OrType ) =>
3504
+ trees = r :: tail
3505
+ if ! l.isNothingType then uniqueTreeMembers += l
3506
+ case OrType (l : OrType , r) =>
3507
+ trees = l :: tail
3508
+ if ! r.isNothingType then uniqueTreeMembers += r
3509
+ case OrType (l, r) =>
3510
+ trees = tail
3511
+ uniqueTreeMembers += l
3512
+ if ! r.isNothingType then uniqueTreeMembers += r
3513
+ }
3514
+ case _ =>
3515
+ }
3516
+ }
3517
+
3518
+ uniqueTreeMembers
3519
+ }
3520
+
3521
+ /** Returns an equivalent union tree without repeated members, preserving order and absorbing
3522
+ * Nothing types, if present. Weaker than LUB.
3510
3523
*/
3511
3524
def deduplicatedAbsorbingNothingTypes (using Context ): Type = {
3525
+
3512
3526
val uniqueTreeMembers = this .gatherTreeUniqueMembersAbsorbingNothingTypes
3513
3527
val factorCount = orFactorCount(isSoft)
3514
3528
3515
3529
uniqueTreeMembers.size match {
3516
3530
case 1 =>
3517
- uniqueTreeMembers.head
3531
+ uniqueTreeMembers.iterator.next()
3518
3532
case uniqueMembersCount if uniqueMembersCount < factorCount =>
3519
- val uniqueMembers = uniqueTreeMembers.iterator
3520
- val startingUnion = OrType (uniqueMembers .next(), uniqueMembers .next(), isSoft)
3521
- uniqueMembers .foldLeft(startingUnion)(OrType (_, _, isSoft))
3533
+ val members = uniqueTreeMembers.iterator
3534
+ val startingUnion = OrType (members .next(), members .next(), isSoft)
3535
+ members .foldLeft(startingUnion)(OrType (_, _, isSoft))
3522
3536
case _ =>
3523
3537
this
3524
3538
}
0 commit comments