Skip to content

Commit f484851

Browse files
committed
Specialize lub for unions over singletons
1 parent dbf2866 commit f484851

File tree

1 file changed

+24
-19
lines changed

1 file changed

+24
-19
lines changed

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

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1530,27 +1530,32 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
15301530
* @note We do not admit singleton types in or-types as lubs.
15311531
*/
15321532
def lub(tp1: Type, tp2: Type, canConstrain: Boolean = false): Type = /*>|>*/ trace(s"lub(${tp1.show}, ${tp2.show}, canConstrain=$canConstrain)", subtyping, show = true) /*<|<*/ {
1533-
if (tp1 eq tp2) tp1
1534-
else if (!tp1.exists) tp1
1535-
else if (!tp2.exists) tp2
1536-
else if ((tp1 isRef AnyClass) || (tp1 isRef AnyKindClass) || (tp2 isRef NothingClass)) tp1
1537-
else if ((tp2 isRef AnyClass) || (tp2 isRef AnyKindClass) || (tp1 isRef NothingClass)) tp2
1538-
else {
1539-
val t1 = mergeIfSuper(tp1, tp2, canConstrain)
1540-
if (t1.exists) t1
1541-
else {
1542-
val t2 = mergeIfSuper(tp2, tp1, canConstrain)
1543-
if (t2.exists) t2
1544-
else {
1545-
def widen(tp: Type) =
1546-
if (ctx.scala2Mode || ctx.erasedTypes) tp.widen else tp.widenIfUnstable
1547-
val tp1w = widen(tp1)
1548-
val tp2w = widen(tp2)
1549-
if ((tp1 ne tp1w) || (tp2 ne tp2w)) lub(tp1w, tp2w)
1550-
else orType(tp1w, tp2w) // no need to check subtypes again
1551-
}
1533+
if (tp1 eq tp2) return tp1
1534+
if (!tp1.exists) return tp1
1535+
if (!tp2.exists) return tp2
1536+
if ((tp1 isRef AnyClass) || (tp1 isRef AnyKindClass) || (tp2 isRef NothingClass)) return tp1
1537+
if ((tp2 isRef AnyClass) || (tp2 isRef AnyKindClass) || (tp1 isRef NothingClass)) return tp2
1538+
val atoms1 = tp1.atoms
1539+
if (atoms1.nonEmpty && !ctx.scala2Mode && !ctx.erasedTypes) {
1540+
val atoms2 = tp2.atoms
1541+
if (atoms2.nonEmpty) {
1542+
if (atoms1.subsetOf(atoms2)) return tp2
1543+
if (atoms2.subsetOf(atoms1)) return tp1
1544+
if ((atoms1 & atoms2).isEmpty) return orType(tp1, tp2)
15521545
}
15531546
}
1547+
val t1 = mergeIfSuper(tp1, tp2, canConstrain)
1548+
if (t1.exists) return t1
1549+
1550+
val t2 = mergeIfSuper(tp2, tp1, canConstrain)
1551+
if (t2.exists) return t2
1552+
1553+
def widen(tp: Type) =
1554+
if (ctx.scala2Mode || ctx.erasedTypes) tp.widen else tp.widenIfUnstable
1555+
val tp1w = widen(tp1)
1556+
val tp2w = widen(tp2)
1557+
if ((tp1 ne tp1w) || (tp2 ne tp2w)) lub(tp1w, tp2w)
1558+
else orType(tp1w, tp2w) // no need to check subtypes again
15541559
}
15551560

15561561
/** The least upper bound of a list of types */

0 commit comments

Comments
 (0)