Skip to content

Commit 340ca06

Browse files
committed
Fixing glb/lub of TypeBounds
Need to take variances into account when forming & or | of bounds. Achieved by moving code from distributeAnd/Or to TypeBounds &/|.
1 parent d8356b6 commit 340ca06

File tree

2 files changed

+22
-25
lines changed

2 files changed

+22
-25
lines changed

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

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -720,7 +720,7 @@ class TypeComparer(initctx: Context) extends DotClass {
720720
else isSubType(tp1, tp2) && isSubType(tp2, tp1)
721721

722722
/** The greatest lower bound of two types */
723-
def glb(tp1: Type, tp2: Type): Type =
723+
def glb(tp1: Type, tp2: Type): Type = /*>|>*/ ctx.traceIndented(s"glb(${tp1.show}, ${tp2.show})", typr, show = true) /*<|<*/ {
724724
if (tp1 eq tp2) tp1
725725
else if (!tp1.exists) tp2
726726
else if (!tp2.exists) tp1
@@ -743,6 +743,7 @@ class TypeComparer(initctx: Context) extends DotClass {
743743
}
744744
}
745745
}
746+
}
746747

747748
/** The greatest lower bound of a list types */
748749
final def glb(tps: List[Type]): Type =
@@ -870,17 +871,10 @@ class TypeComparer(initctx: Context) extends DotClass {
870871

871872
/** Try to distribute `&` inside type, detect and handle conflicts */
872873
private def distributeAnd(tp1: Type, tp2: Type): Type = tp1 match {
873-
case tp1 @ TypeBounds(lo1, hi1) =>
874+
case tp1: TypeBounds =>
874875
tp2 match {
875-
case tp2 @ TypeBounds(lo2, hi2) =>
876-
if ((lo1 eq hi1) && (lo2 eq hi2)) {
877-
val v = tp1 commonVariance tp2
878-
if (v > 0) return TypeAlias(hi1 & hi2, v)
879-
if (v < 0) return TypeAlias(lo1 | lo2, v)
880-
}
881-
TypeBounds(lo1 | lo2, hi1 & hi2)
882-
case _ =>
883-
andConflict(tp1, tp2)
876+
case tp2: TypeBounds => tp1 & tp2
877+
case _ => andConflict(tp1, tp2)
884878
}
885879
case tp1: ClassInfo =>
886880
tp2 match {
@@ -944,17 +938,10 @@ class TypeComparer(initctx: Context) extends DotClass {
944938

945939
/** Try to distribute `|` inside type, detect and handle conflicts */
946940
private def distributeOr(tp1: Type, tp2: Type): Type = tp1 match {
947-
case tp1 @ TypeBounds(lo1, hi1) =>
941+
case tp1: TypeBounds =>
948942
tp2 match {
949-
case tp2 @ TypeBounds(lo2, hi2) =>
950-
if ((lo1 eq hi1) && (lo2 eq hi2)) {
951-
val v = tp1 commonVariance tp2
952-
if (v > 0) return TypeAlias(hi1 | hi2, v)
953-
if (v < 0) return TypeAlias(lo1 & lo2, v)
954-
}
955-
TypeBounds(lo1 & lo2, hi1 | hi2)
956-
case _ =>
957-
orConflict(tp1, tp2)
943+
case tp2: TypeBounds => tp1 | tp2
944+
case _ => orConflict(tp1, tp2)
958945
}
959946
case tp1: ClassInfo =>
960947
tp2 match {

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

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1883,11 +1883,21 @@ object Types {
18831883

18841884
def contains(tp: Type)(implicit ctx: Context) = lo <:< tp && tp <:< hi
18851885

1886-
def & (that: TypeBounds)(implicit ctx: Context): TypeBounds =
1887-
derivedTypeBounds(this.lo | that.lo, this.hi & that.hi, this commonVariance that)
1886+
def & (that: TypeBounds)(implicit ctx: Context): TypeBounds = {
1887+
val v = this commonVariance that
1888+
if (v != 0 && (this.lo eq this.hi) && (that.lo eq that.hi))
1889+
if (v > 0) derivedTypeAlias(this.hi & that.hi, v)
1890+
else derivedTypeAlias(this.lo | that.lo, v)
1891+
else derivedTypeBounds(this.lo | that.lo, this.hi & that.hi, v)
1892+
}
18881893

1889-
def | (that: TypeBounds)(implicit ctx: Context): TypeBounds =
1890-
derivedTypeBounds(this.lo & that.lo, this.hi | that.hi, this commonVariance that)
1894+
def | (that: TypeBounds)(implicit ctx: Context): TypeBounds = {
1895+
val v = this commonVariance that
1896+
if (v == 0 && (this.lo eq this.hi) && (that.lo eq that.hi))
1897+
if (v > 0) derivedTypeAlias(this.hi | that.hi, v)
1898+
else derivedTypeAlias(this.lo & that.lo, v)
1899+
else derivedTypeBounds(this.lo & that.lo, this.hi | that.hi, v)
1900+
}
18911901

18921902
override def & (that: Type)(implicit ctx: Context) = that match {
18931903
case that: TypeBounds => this & that

0 commit comments

Comments
 (0)