Skip to content

Commit 53979ee

Browse files
committed
Revert "Reimplement TypeErasure#erasedLub with the documented algorithm"
This reverts commit c12a6fd.
1 parent ec74656 commit 53979ee

File tree

1 file changed

+19
-33
lines changed

1 file changed

+19
-33
lines changed

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

Lines changed: 19 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -226,8 +226,7 @@ object TypeErasure {
226226
* S is last : in the linearization of the first argument type `tp1`
227227
* there are no minimal common superclasses or traits that
228228
* come after S.
229-
* The reason to pick last is that we prefer classes over traits that way,
230-
* which leads to more predictable bytecode and (?) faster dynamic dispatch.
229+
* (the reason to pick last is that we prefer classes over traits that way).
231230
*/
232231
def erasedLub(tp1: Type, tp2: Type)(implicit ctx: Context): Type = tp1 match {
233232
case JavaArrayType(elem1) =>
@@ -246,38 +245,25 @@ object TypeErasure {
246245
case JavaArrayType(_) => defn.ObjectType
247246
case _ =>
248247
val cls2 = tp2.classSymbol
249-
250-
/** takeWhile+1 */
251-
def takeUntil[T](l: List[T])(f: T => Boolean): List[T] = {
252-
@tailrec def loop(tail: List[T], acc: List[T]): List[T] =
253-
tail match {
254-
case h :: t => loop(if (f(h)) t else Nil, h :: acc)
255-
case Nil => acc.reverse
256-
}
257-
loop(l, Nil)
258-
}
259-
260-
// We are not interested in anything that is not a supertype of tp2
261-
val tp2superclasses = tp1.baseClasses.filter(cls2.derivesFrom)
262-
263-
// From the spec, "Linearization also satisfies the property that a
264-
// linearization of a class always contains the linearization of its
265-
// direct superclass as a suffix"; it's enought to consider every
266-
// candidate up to the first class.
267-
val candidates = takeUntil(tp2superclasses)(!_.is(Trait))
268-
269-
// Candidates st "no other common superclass or trait derives from S"
270-
val minimums = candidates.filter { cand =>
271-
candidates.forall(x => !x.derivesFrom(cand) || x.eq(cand))
272-
}
273-
274-
// Pick the last minimum to prioritise classes over traits
275-
minimums.lastOption match {
276-
case Some(lub) if lub != defn.AnyClass && lub != defn.AnyValClass =>
277-
lub.typeRef
278-
case _ => // Any/AnyVal only exist before erasure
279-
defn.ObjectType
248+
@tailrec def loop(bcs: List[ClassSymbol], bestSoFar: ClassSymbol): ClassSymbol = bcs match {
249+
case bc :: bcs1 =>
250+
if (cls2.derivesFrom(bc)) {
251+
val newBest = if (bestSoFar.derivesFrom(bc)) bestSoFar else bc
252+
253+
if (!bc.is(Trait) && bc != defn.AnyClass)
254+
newBest
255+
else
256+
loop(bcs1, newBest)
257+
} else
258+
loop(bcs1, bestSoFar)
259+
case nil =>
260+
bestSoFar
280261
}
262+
val t = loop(tp1.baseClasses, defn.ObjectClass)
263+
if (t eq defn.AnyValClass)
264+
// while AnyVal is a valid common super class for primitives it does not exist after erasure
265+
defn.ObjectType
266+
else t.typeRef
281267
}
282268
}
283269

0 commit comments

Comments
 (0)