aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 =>