Skip to content

Commit cd2a20a

Browse files
committed
GADTs: freeze when joining LHS union
These approximations shouldn't be used to derive GADTs constraints, just as the .widenSingleton approx shouldn't.
1 parent 5dded52 commit cd2a20a

File tree

1 file changed

+10
-3
lines changed

1 file changed

+10
-3
lines changed

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -431,18 +431,25 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
431431
case Some(b) => return b
432432
case None =>
433433

434+
/** `recur` shouldn't normally be used with approximated types, according to its
435+
* documentation. In the specific examples where this function is
436+
* called, it is sound to do so as long as we freeze GADTs.
437+
*/
438+
def recurInFrozenGadt(tp1: Type, tp2: Type) =
439+
inFrozenGadt { recur(tp1, tp2) }
440+
434441
def widenOK =
435442
(tp2.widenSingletons eq tp2)
436443
&& (tp1.widenSingletons ne tp1)
437-
&& inFrozenGadt { recur(tp1.widenSingletons, tp2) }
444+
&& recurInFrozenGadt(tp1.widenSingletons, tp2)
438445

439446
def joinOK = tp2.dealiasKeepRefiningAnnots match {
440447
case tp2: AppliedType if !tp2.tycon.typeSymbol.isClass =>
441448
// If we apply the default algorithm for `A[X] | B[Y] <: C[Z]` where `C` is a
442449
// type parameter, we will instantiate `C` to `A` and then fail when comparing
443450
// with `B[Y]`. To do the right thing, we need to instantiate `C` to the
444451
// common superclass of `A` and `B`.
445-
recur(tp1.join, tp2)
452+
recurInFrozenGadt(tp1.join, tp2)
446453
case _ =>
447454
false
448455
}
@@ -469,7 +476,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
469476
widenOK
470477
|| joinOK
471478
|| (tp1.isSoft || constrainRHSVars(tp2)) && recur(tp11, tp2) && recur(tp12, tp2)
472-
|| containsAnd(tp1) && recur(tp1.join, tp2)
479+
|| containsAnd(tp1) && recurInFrozenGadt(tp1.join, tp2)
473480
case tp1: MatchType =>
474481
val reduced = tp1.reduced
475482
if (reduced.exists) recur(reduced, tp2) else thirdTry

0 commit comments

Comments
 (0)