@@ -226,8 +226,7 @@ object TypeErasure {
226
226
* S is last : in the linearization of the first argument type `tp1`
227
227
* there are no minimal common superclasses or traits that
228
228
* 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).
231
230
*/
232
231
def erasedLub (tp1 : Type , tp2 : Type )(implicit ctx : Context ): Type = tp1 match {
233
232
case JavaArrayType (elem1) =>
@@ -246,38 +245,25 @@ object TypeErasure {
246
245
case JavaArrayType (_) => defn.ObjectType
247
246
case _ =>
248
247
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
280
261
}
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
281
267
}
282
268
}
283
269
0 commit comments