diff options
author | Martin Odersky <odersky@gmail.com> | 2016-08-22 15:46:06 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2016-08-26 11:13:15 +0200 |
commit | 23d1bfb4111d8aff513659f2b3e3dd695b9b6e03 (patch) | |
tree | 500cb526bde1bdb56707f6606c551a6c6eb573e9 | |
parent | f5972c7904ce802e3e7668094726c21c3a603419 (diff) | |
download | dotty-23d1bfb4111d8aff513659f2b3e3dd695b9b6e03.tar.gz dotty-23d1bfb4111d8aff513659f2b3e3dd695b9b6e03.tar.bz2 dotty-23d1bfb4111d8aff513659f2b3e3dd695b9b6e03.zip |
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.
-rw-r--r-- | src/dotty/tools/dotc/core/TypeComparer.scala | 19 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 5 |
2 files changed, 21 insertions, 3 deletions
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala index 8d7e9d164..e9300c0ba 100644 --- a/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/src/dotty/tools/dotc/core/TypeComparer.scala @@ -76,6 +76,19 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { myNothingType } + /** Indicates whether a previous subtype check used GADT bounds */ + var GADTused = false + + /** Record that GADT bounds of `sym` were used in a subtype check. + * But exclude constructor type parameters, as these are aliased + * to the corresponding class parameters, which does not constitute + * a true usage of a GADT symbol. + */ + private def GADTusage(sym: Symbol) = { + if (!sym.owner.isConstructor) GADTused = true + true + } + // Subtype testing `<:<` def topLevelSubType(tp1: Type, tp2: Type): Boolean = { @@ -325,7 +338,8 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { val gbounds2 = ctx.gadt.bounds(tp2.symbol) (gbounds2 != null) && (isSubTypeWhenFrozen(tp1, gbounds2.lo) || - narrowGADTBounds(tp2, tp1, isUpper = false)) + narrowGADTBounds(tp2, tp1, isUpper = false)) && + GADTusage(tp2.symbol) } ((frozenConstraint || !isCappable(tp1)) && isSubType(tp1, lo2) || compareGADT || @@ -507,7 +521,8 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { val gbounds1 = ctx.gadt.bounds(tp1.symbol) (gbounds1 != null) && (isSubTypeWhenFrozen(gbounds1.hi, tp2) || - narrowGADTBounds(tp1, tp2, isUpper = true)) + narrowGADTBounds(tp1, tp2, isUpper = true)) && + GADTusage(tp1.symbol) } isSubType(hi1, tp2) || compareGADT case _ => diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 7eb022b51..39d9d267e 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -1715,6 +1715,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit else missingArgs case _ => + ctx.typeComparer.GADTused = false if (ctx.mode is Mode.Pattern) { tree match { case _: RefTree | _: Literal if !isVarPattern(tree) => @@ -1723,7 +1724,9 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit } tree } - else if (tree.tpe <:< pt) tree + else if (tree.tpe <:< pt) + if (ctx.typeComparer.GADTused) tree.asInstance(pt) + else tree else if (wtp.isInstanceOf[MethodType]) missingArgs else { typr.println(i"adapt to subtype ${tree.tpe} !<:< $pt") |