aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-08-10 17:48:52 +0200
committerMartin Odersky <odersky@gmail.com>2014-08-10 18:32:52 +0200
commitc2cdd3a3dca2a629923327046b213addd93499fc (patch)
treef893acbf9ab062c96c53d00215a6076f997e84b4 /src/dotty/tools
parentbbf777a729e5b6e8c8a75466c42004d3ff4c5d32 (diff)
downloaddotty-c2cdd3a3dca2a629923327046b213addd93499fc.tar.gz
dotty-c2cdd3a3dca2a629923327046b213addd93499fc.tar.bz2
dotty-c2cdd3a3dca2a629923327046b213addd93499fc.zip
More targeted eta-lifting
Eta-lifting picked some arbitrary base type. It turned out that i94-nada failed once we add a product trait to case classes (in the next commit) because Eta-Kifting picked Product as the base type, even though the target type was bounded by Monad. We now change the scheme so that the target type is included in the lifting, in order to avoid that we lift to useless types.
Diffstat (limited to 'src/dotty/tools')
-rw-r--r--src/dotty/tools/dotc/config/Printers.scala1
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala23
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala6
-rw-r--r--src/dotty/tools/dotc/typer/VarianceChecker.scala3
4 files changed, 19 insertions, 14 deletions
diff --git a/src/dotty/tools/dotc/config/Printers.scala b/src/dotty/tools/dotc/config/Printers.scala
index 5bfe1d0b6..0cbfb6880 100644
--- a/src/dotty/tools/dotc/config/Printers.scala
+++ b/src/dotty/tools/dotc/config/Printers.scala
@@ -23,6 +23,7 @@ object Printers {
val completions = noPrinter
val gadts = noPrinter
val hk = noPrinter
+ val variances = noPrinter
val incremental = noPrinter
val config = noPrinter
val transforms = noPrinter
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index c63788ec9..2c8e9902b 100644
--- a/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -463,16 +463,18 @@ class TypeApplications(val self: Type) extends AnyVal {
self.appliedTo(tparams map (_.typeRef)).LambdaAbstract(tparams)
}
- /** If this type has a base type `B[T1, ..., Tn]` where the type parameters
- * of `B` match one-by-one the variances of `tparams`, convert it to
+ /** Test whether this type has a base type `B[T1, ..., Tn]` where the type parameters
+ * of `B` match one-by-one the variances of `tparams`, and where the lambda
+ * abstracted type
*
* LambdaXYZ { type Apply = B[$hkArg$0, ..., $hkArg$n] }
* { type $hkArg$0 = T1; ...; type $hkArg$n = Tn }
*
+ * satisfies predicate `p`. Try base types in the order of ther occurrence in `baseClasses`.
* A type parameter matches a varianve V if it has V as its variance or if V == 0.
*/
- def EtaLiftTo(tparams: List[Symbol])(implicit ctx: Context): Type = {
- def tryLift(bcs: List[ClassSymbol]): Type = bcs match {
+ def testLifted(tparams: List[Symbol], p: Type => Boolean)(implicit ctx: Context): Boolean = {
+ def tryLift(bcs: List[ClassSymbol]): Boolean = bcs match {
case bc :: bcs1 =>
val tp = self.baseTypeWithArgs(bc)
val targs = tp.argInfos
@@ -481,19 +483,20 @@ class TypeApplications(val self: Type) extends AnyVal {
param2.variance == param2.variance || param2.variance == 0
if ((tycon.typeParams corresponds tparams)(variancesMatch)) {
val expanded = tycon.EtaExpand
- val res = (expanded /: targs) { (partialInst, targ) =>
+ val lifted = (expanded /: targs) { (partialInst, targ) =>
val tparam = partialInst.typeParams.head
RefinedType(partialInst, tparam.name, targ.bounds.withVariance(tparam.variance))
}
- hk.println(i"eta lifting $self --> $res")
- res
+ ctx.traceIndented(i"eta lifting $self --> $lifted", hk) {
+ p(lifted) || tryLift(bcs1)
+ }
}
else tryLift(bcs1)
case nil =>
- NoType
+ false
}
- if (tparams.isEmpty) NoType
- else if (typeParams.nonEmpty) EtaExpand
+ if (tparams.isEmpty) false
+ else if (typeParams.nonEmpty) p(EtaExpand)
else tryLift(self.baseClasses)
}
} \ No newline at end of file
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index 797712459..48286fe47 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -454,7 +454,7 @@ class TypeComparer(initctx: Context) extends DotClass {
def isHKSubType = tp2.name == tpnme.Apply && {
val lambda2 = tp2.prefix.LambdaClass(forcing = true)
lambda2.exists && !tp1.isLambda &&
- isSubType(tp1.EtaLiftTo(lambda2.typeParams), tp2.prefix)
+ tp1.testLifted(lambda2.typeParams, isSubType(_, tp2.prefix))
}
def compareNamed = {
implicit val ctx: Context = this.ctx // Dotty deviation: implicits need explicit type
@@ -673,7 +673,7 @@ class TypeComparer(initctx: Context) extends DotClass {
|| hasMatchingMember(name2)
|| fourthTry(tp1, tp2)
)
- || needsEtaLift(tp1, tp2) && isSubType(tp1.EtaLiftTo(tp2.typeParams), tp2)
+ || needsEtaLift(tp1, tp2) && tp1.testLifted(tp2.typeParams, isSubType(_, tp2))
)
}
compareRefined
@@ -768,7 +768,7 @@ class TypeComparer(initctx: Context) extends DotClass {
isNewSubType(tp1.parent, tp2)
}
finally pendingRefinedBases = saved
- } || needsEtaLift(tp2, tp1) && isSubType(tp1, tp2.EtaLiftTo(tp1.typeParams))
+ } || needsEtaLift(tp2, tp1) && tp2.testLifted(tp1.typeParams, isSubType(tp1, _))
case AndType(tp11, tp12) =>
isNewSubType(tp11, tp2) || isNewSubType(tp12, tp2)
case _ =>
diff --git a/src/dotty/tools/dotc/typer/VarianceChecker.scala b/src/dotty/tools/dotc/typer/VarianceChecker.scala
index 9ce3ca0b7..5865f0133 100644
--- a/src/dotty/tools/dotc/typer/VarianceChecker.scala
+++ b/src/dotty/tools/dotc/typer/VarianceChecker.scala
@@ -6,6 +6,7 @@ import core._
import Types._, Contexts._, Flags._, Symbols._, Annotations._, Trees._, NameOps._
import Decorators._
import Variances._
+import config.Printers.variances
/** Provides `check` method to check that all top-level definitions
* in tree are variance correct. Does not recurse inside methods.
@@ -77,7 +78,7 @@ class VarianceChecker()(implicit ctx: Context) {
* explicitly (their TypeDefs will be passed here.) For MethodTypes, the
* same is true of the parameters (ValDefs).
*/
- def apply(status: Option[VarianceError], tp: Type): Option[VarianceError] = ctx.traceIndented(s"variance checking $tp of $base at $variance") {
+ def apply(status: Option[VarianceError], tp: Type): Option[VarianceError] = ctx.traceIndented(s"variance checking $tp of $base at $variance", variances) {
if (status.isDefined) status
else tp match {
case tp: TypeRef =>