Skip to content

Commit 0fde265

Browse files
committed
Make computation of baseClasses for And/OrTypes more efficient.
1 parent 0f708eb commit 0fde265

File tree

3 files changed

+42
-15
lines changed

3 files changed

+42
-15
lines changed

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2077,6 +2077,11 @@ object SymDenotations {
20772077
def contains(sym: Symbol): Boolean = contains(sym, classIds.length)
20782078
}
20792079

2080+
object BaseClassSet {
2081+
def apply(bcs: List[ClassSymbol]): BaseClassSet =
2082+
new BaseClassSet(bcs.toArray.map(_.id))
2083+
}
2084+
20802085
/** A class to combine base data from parent types */
20812086
class BaseDataBuilder {
20822087
private var classes: List[ClassSymbol] = Nil
@@ -2089,20 +2094,18 @@ object SymDenotations {
20892094
classIds = classIds1
20902095
}
20912096

2092-
private def contains(sym: Symbol): Boolean =
2093-
new BaseClassSet(classIds).contains(sym, length)
2094-
20952097
private def add(sym: Symbol): Unit = {
20962098
if (length == classIds.length) resize(length * 2)
20972099
classIds(length) = sym.id
20982100
length += 1
20992101
}
21002102

21012103
def addAll(bcs: List[ClassSymbol]): this.type = {
2104+
val len = length
21022105
bcs match {
21032106
case bc :: bcs1 =>
21042107
addAll(bcs1)
2105-
if (!contains(bc)) {
2108+
if (!new BaseClassSet(classIds).contains(bc, len)) {
21062109
add(bc)
21072110
classes = bc :: classes
21082111
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1161,7 +1161,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
11611161
// However, maybe we can still apply the replacement to
11621162
// types which are not explicitly written.
11631163
defn.NothingType
1164-
case _ => andType(tp1, tp2)
1164+
case _ => andType(tp1, tp2)
11651165
}
11661166
case _ => andType(tp1, tp2)
11671167
}

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

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -384,22 +384,15 @@ object Types {
384384

385385
/** The base classes of this type as determined by ClassDenotation
386386
* in linearization order, with the class itself as first element.
387-
* For AndTypes/OrTypes, the merge/intersection of the operands' baseclasses.
388-
* Inherited by all type proxies. `Nil` for all other types.
387+
* Inherited by all type proxies. Overridden for And and Or types.
388+
* `Nil` for all other types.
389389
*/
390-
final def baseClasses(implicit ctx: Context): List[ClassSymbol] = track("baseClasses") {
390+
def baseClasses(implicit ctx: Context): List[ClassSymbol] = track("baseClasses") {
391391
this match {
392392
case tp: TypeProxy =>
393393
tp.underlying.baseClasses
394394
case tp: ClassInfo =>
395395
tp.cls.baseClasses
396-
case AndType(tp1, tp2) =>
397-
(new BaseDataBuilder)
398-
.addAll(tp1.baseClasses)
399-
.addAll(tp2.baseClasses)
400-
.baseClasses
401-
case OrType(tp1, tp2) =>
402-
tp1.baseClasses intersect tp2.baseClasses
403396
case _ => Nil
404397
}
405398
}
@@ -2307,6 +2300,37 @@ object Types {
23072300
def tp2: Type
23082301
def isAnd: Boolean
23092302
def derivedAndOrType(tp1: Type, tp2: Type)(implicit ctx: Context): Type // needed?
2303+
2304+
private[this] var myBaseClassesPeriod: Period = Nowhere
2305+
private[this] var myBaseClasses: List[ClassSymbol] = _
2306+
2307+
/** Base classes of And are the merge of the operand base classes
2308+
* For OrTypes, it's the intersection.
2309+
*/
2310+
override final def baseClasses(implicit ctx: Context) = {
2311+
if (myBaseClassesPeriod != ctx.period) {
2312+
val bcs1 = tp1.baseClasses
2313+
val bcs1set = BaseClassSet(bcs1)
2314+
def recur(bcs2: List[ClassSymbol]): List[ClassSymbol] = bcs2 match {
2315+
case bc2 :: bcs2rest =>
2316+
if (isAnd)
2317+
if (bcs1set contains bc2)
2318+
if (bc2.is(Trait)) recur(bcs2rest)
2319+
else bcs1 // common class, therefore rest is the same in both sequences
2320+
else bc2 :: recur(bcs2rest)
2321+
else
2322+
if (bcs1set contains bc2)
2323+
if (bc2.is(Trait)) bc2 :: recur(bcs2rest)
2324+
else bcs2rest
2325+
else recur(bcs2rest)
2326+
case nil =>
2327+
if (isAnd) bcs1 else bcs2
2328+
}
2329+
myBaseClasses = recur(tp2.baseClasses)
2330+
myBaseClassesPeriod = ctx.period
2331+
}
2332+
myBaseClasses
2333+
}
23102334
}
23112335

23122336
abstract case class AndType(tp1: Type, tp2: Type) extends CachedGroundType with AndOrType {

0 commit comments

Comments
 (0)