Skip to content

Commit 9bb1d4a

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 0910204 commit 9bb1d4a

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
@@ -1679,6 +1679,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
16791679
else
16801680
missingArgs
16811681
case _ =>
1682+
ctx.typeComparer.GADTused = false
16821683
if (ctx.mode is Mode.Pattern) {
16831684
tree match {
16841685
case _: RefTree | _: Literal if !isVarPattern(tree) =>
@@ -1687,7 +1688,9 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
16871688
}
16881689
tree
16891690
}
1690-
else if (tree.tpe <:< pt) tree
1691+
else if (tree.tpe <:< pt)
1692+
if (ctx.typeComparer.GADTused) tree.asInstance(pt)
1693+
else tree
16911694
else if (wtp.isInstanceOf[MethodType]) missingArgs
16921695
else {
16931696
typr.println(i"adapt to subtype ${tree.tpe} !<:< $pt")

0 commit comments

Comments
 (0)