Skip to content

Commit a555606

Browse files
committed
Optimized Types.gatherTreeUniqueMembersAbsorbingNothingTypes
- Replaced recursion by a while loop - Replaced immutable.Set by EqLinkedHashSet
1 parent 28f855d commit a555606

File tree

1 file changed

+40
-26
lines changed

1 file changed

+40
-26
lines changed

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ import java.lang.ref.WeakReference
3838
import compiletime.uninitialized
3939
import cc.{CapturingType, CaptureSet, derivedCapturingType, isBoxedCapturing, EventuallyCapturingType, boxedUnlessFun}
4040
import CaptureSet.{CompareResult, IdempotentCaptRefMap, IdentityCaptRefMap}
41+
import scala.collection.mutable.ListBuffer
42+
import dotty.tools.dotc.util._
4143

4244
import scala.annotation.internal.sharable
4345
import scala.annotation.threadUnsafe
@@ -3485,40 +3487,52 @@ object Types {
34853487

34863488
/** Returns the set of non-union (leaf) types composing this union tree with Nothing types
34873489
* 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.
35103523
*/
35113524
def deduplicatedAbsorbingNothingTypes(using Context): Type = {
3525+
35123526
val uniqueTreeMembers = this.gatherTreeUniqueMembersAbsorbingNothingTypes
35133527
val factorCount = orFactorCount(isSoft)
35143528

35153529
uniqueTreeMembers.size match {
35163530
case 1 =>
3517-
uniqueTreeMembers.head
3531+
uniqueTreeMembers.iterator.next()
35183532
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))
35223536
case _ =>
35233537
this
35243538
}

0 commit comments

Comments
 (0)