Skip to content

Commit 23d1bfb

Browse files
committed
Make expressions using GADTs type check in later phases
GADT logic is lost after PatMat. To make code typecheck, the typer should already insert casts where a subtype check succeeded because it involved bounds established by a GADT comparison.
1 parent f5972c7 commit 23d1bfb

File tree

2 files changed

+21
-3
lines changed

2 files changed

+21
-3
lines changed

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

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,19 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
7676
myNothingType
7777
}
7878

79+
/** Indicates whether a previous subtype check used GADT bounds */
80+
var GADTused = false
81+
82+
/** Record that GADT bounds of `sym` were used in a subtype check.
83+
* But exclude constructor type parameters, as these are aliased
84+
* to the corresponding class parameters, which does not constitute
85+
* a true usage of a GADT symbol.
86+
*/
87+
private def GADTusage(sym: Symbol) = {
88+
if (!sym.owner.isConstructor) GADTused = true
89+
true
90+
}
91+
7992
// Subtype testing `<:<`
8093

8194
def topLevelSubType(tp1: Type, tp2: Type): Boolean = {
@@ -325,7 +338,8 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
325338
val gbounds2 = ctx.gadt.bounds(tp2.symbol)
326339
(gbounds2 != null) &&
327340
(isSubTypeWhenFrozen(tp1, gbounds2.lo) ||
328-
narrowGADTBounds(tp2, tp1, isUpper = false))
341+
narrowGADTBounds(tp2, tp1, isUpper = false)) &&
342+
GADTusage(tp2.symbol)
329343
}
330344
((frozenConstraint || !isCappable(tp1)) && isSubType(tp1, lo2) ||
331345
compareGADT ||
@@ -507,7 +521,8 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
507521
val gbounds1 = ctx.gadt.bounds(tp1.symbol)
508522
(gbounds1 != null) &&
509523
(isSubTypeWhenFrozen(gbounds1.hi, tp2) ||
510-
narrowGADTBounds(tp1, tp2, isUpper = true))
524+
narrowGADTBounds(tp1, tp2, isUpper = true)) &&
525+
GADTusage(tp1.symbol)
511526
}
512527
isSubType(hi1, tp2) || compareGADT
513528
case _ =>

src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1715,6 +1715,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
17151715
else
17161716
missingArgs
17171717
case _ =>
1718+
ctx.typeComparer.GADTused = false
17181719
if (ctx.mode is Mode.Pattern) {
17191720
tree match {
17201721
case _: RefTree | _: Literal if !isVarPattern(tree) =>
@@ -1723,7 +1724,9 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
17231724
}
17241725
tree
17251726
}
1726-
else if (tree.tpe <:< pt) tree
1727+
else if (tree.tpe <:< pt)
1728+
if (ctx.typeComparer.GADTused) tree.asInstance(pt)
1729+
else tree
17271730
else if (wtp.isInstanceOf[MethodType]) missingArgs
17281731
else {
17291732
typr.println(i"adapt to subtype ${tree.tpe} !<:< $pt")

0 commit comments

Comments
 (0)