Skip to content

Commit 399fc02

Browse files
committed
Clean up and document tricky logic in TypeComparer
1 parent 4ca09d8 commit 399fc02

File tree

1 file changed

+17
-3
lines changed

1 file changed

+17
-3
lines changed

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

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -573,11 +573,25 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
573573
}
574574
compareTypeLambda
575575
case OrType(tp21, tp22) =>
576+
// The next clause handles a situation like the one encountered in i2745.scala.
577+
// We have:
578+
//
579+
// x: A | B, x.type <:< A | X where X is a type variable
580+
//
581+
// We should instantiate X to B instead of x.type or A | B. To do this, we widen
582+
// the LHS to A | B and recur *without indicating that this is a lowApprox*. The
583+
// latter point is important since otherwise we would not get to instantiate X.
584+
// If that succeeds, fine. If not we continue and hit the `either` below.
585+
// That second path is important to handle comparisons with unions of singletons,
586+
// as in `1 <:< 1 | 2`.
576587
val tp1w = tp1.widen
577-
val tp1a = tp1w.dealiasKeepRefiningAnnots
588+
if ((tp1w ne tp1) && recur(tp1w, tp2))
589+
return true
590+
591+
val tp1a = tp1.dealiasKeepRefiningAnnots
578592
if (tp1a ne tp1)
579-
// Follow the alias; this might avoid truncating the search space in the either below
580-
return recur(tp1a, tp2) || (tp1w ne tp1) && isSubType(tp1w, tp2, approx.addLow)
593+
// Follow the alias; this might lead to an OrType on the left which needs to be split
594+
return recur(tp1a, tp2)
581595

582596
// Rewrite T1 <: (T211 & T212) | T22 to T1 <: (T211 | T22) and T1 <: (T212 | T22)
583597
// and analogously for T1 <: T21 | (T221 & T222)

0 commit comments

Comments
 (0)