@@ -363,21 +363,13 @@ object TypeErasure {
363
363
* which leads to more predictable bytecode and (?) faster dynamic dispatch.
364
364
*/
365
365
def erasedLub (tp1 : Type , tp2 : Type )(using Context ): Type = {
366
- // After erasure, C | {Null, Nothing} is just C, if C is a reference type.
367
- // We need to short-circuit this case here because the regular lub logic below
368
- // relies on the class hierarchy, which doesn't properly capture `Null`/`Nothing`s subtyping
369
- // behaviour.
370
- if (tp1.isBottomTypeAfterErasure && tp2.derivesFrom(defn.ObjectClass )) return tp2
371
- if (tp2.isBottomTypeAfterErasure && tp1.derivesFrom(defn.ObjectClass )) return tp1
372
-
373
- // After erasure, A | Nothing is just A, if A is a value type.
374
- // We need to short-circuit this case here because the regular lub logic below
375
- // relies on the class hierarchy, which doesn't properly capture `Nothing`s subtyping
376
- // behaviour.
377
- if (tp1.isExactlyNothing && tp2.derivesFrom(defn.AnyValClass )) return valueErasure(tp2)
378
- if (tp2.isExactlyNothing && tp1.derivesFrom(defn.AnyValClass )) return valueErasure(tp1)
379
-
380
- tp1 match {
366
+ // We need to short-circuit the following 2 case because the regular lub logic in the else relies on
367
+ // the class hierarchy, which doesn't properly capture `Nothing`/`Null` subtyping behaviour.
368
+ if tp1.isRef(defn.NothingClass ) || (tp1.isRef(defn.NullClass ) && tp2.derivesFrom(defn.ObjectClass )) then
369
+ tp2 // After erasure, Nothing | T is just T and Null | C is just C, if C is a reference type.
370
+ else if tp2.isRef(defn.NothingClass ) || (tp2.isRef(defn.NullClass ) && tp1.derivesFrom(defn.ObjectClass )) then
371
+ tp1 // After erasure, T | Nothing is just T and C | Null is just C, if C is a reference type.
372
+ else tp1 match {
381
373
case JavaArrayType (elem1) =>
382
374
import dotty .tools .dotc .transform .TypeUtils ._
383
375
tp2 match {
0 commit comments