Skip to content

Commit c2cdd3a

Browse files
committed
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.
1 parent bbf777a commit c2cdd3a

File tree

4 files changed

+19
-14
lines changed

4 files changed

+19
-14
lines changed

src/dotty/tools/dotc/config/Printers.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ object Printers {
2323
val completions = noPrinter
2424
val gadts = noPrinter
2525
val hk = noPrinter
26+
val variances = noPrinter
2627
val incremental = noPrinter
2728
val config = noPrinter
2829
val transforms = noPrinter

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

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -463,16 +463,18 @@ class TypeApplications(val self: Type) extends AnyVal {
463463
self.appliedTo(tparams map (_.typeRef)).LambdaAbstract(tparams)
464464
}
465465

466-
/** If this type has a base type `B[T1, ..., Tn]` where the type parameters
467-
* of `B` match one-by-one the variances of `tparams`, convert it to
466+
/** Test whether this type has a base type `B[T1, ..., Tn]` where the type parameters
467+
* of `B` match one-by-one the variances of `tparams`, and where the lambda
468+
* abstracted type
468469
*
469470
* LambdaXYZ { type Apply = B[$hkArg$0, ..., $hkArg$n] }
470471
* { type $hkArg$0 = T1; ...; type $hkArg$n = Tn }
471472
*
473+
* satisfies predicate `p`. Try base types in the order of ther occurrence in `baseClasses`.
472474
* A type parameter matches a varianve V if it has V as its variance or if V == 0.
473475
*/
474-
def EtaLiftTo(tparams: List[Symbol])(implicit ctx: Context): Type = {
475-
def tryLift(bcs: List[ClassSymbol]): Type = bcs match {
476+
def testLifted(tparams: List[Symbol], p: Type => Boolean)(implicit ctx: Context): Boolean = {
477+
def tryLift(bcs: List[ClassSymbol]): Boolean = bcs match {
476478
case bc :: bcs1 =>
477479
val tp = self.baseTypeWithArgs(bc)
478480
val targs = tp.argInfos
@@ -481,19 +483,20 @@ class TypeApplications(val self: Type) extends AnyVal {
481483
param2.variance == param2.variance || param2.variance == 0
482484
if ((tycon.typeParams corresponds tparams)(variancesMatch)) {
483485
val expanded = tycon.EtaExpand
484-
val res = (expanded /: targs) { (partialInst, targ) =>
486+
val lifted = (expanded /: targs) { (partialInst, targ) =>
485487
val tparam = partialInst.typeParams.head
486488
RefinedType(partialInst, tparam.name, targ.bounds.withVariance(tparam.variance))
487489
}
488-
hk.println(i"eta lifting $self --> $res")
489-
res
490+
ctx.traceIndented(i"eta lifting $self --> $lifted", hk) {
491+
p(lifted) || tryLift(bcs1)
492+
}
490493
}
491494
else tryLift(bcs1)
492495
case nil =>
493-
NoType
496+
false
494497
}
495-
if (tparams.isEmpty) NoType
496-
else if (typeParams.nonEmpty) EtaExpand
498+
if (tparams.isEmpty) false
499+
else if (typeParams.nonEmpty) p(EtaExpand)
497500
else tryLift(self.baseClasses)
498501
}
499502
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ class TypeComparer(initctx: Context) extends DotClass {
454454
def isHKSubType = tp2.name == tpnme.Apply && {
455455
val lambda2 = tp2.prefix.LambdaClass(forcing = true)
456456
lambda2.exists && !tp1.isLambda &&
457-
isSubType(tp1.EtaLiftTo(lambda2.typeParams), tp2.prefix)
457+
tp1.testLifted(lambda2.typeParams, isSubType(_, tp2.prefix))
458458
}
459459
def compareNamed = {
460460
implicit val ctx: Context = this.ctx // Dotty deviation: implicits need explicit type
@@ -673,7 +673,7 @@ class TypeComparer(initctx: Context) extends DotClass {
673673
|| hasMatchingMember(name2)
674674
|| fourthTry(tp1, tp2)
675675
)
676-
|| needsEtaLift(tp1, tp2) && isSubType(tp1.EtaLiftTo(tp2.typeParams), tp2)
676+
|| needsEtaLift(tp1, tp2) && tp1.testLifted(tp2.typeParams, isSubType(_, tp2))
677677
)
678678
}
679679
compareRefined
@@ -768,7 +768,7 @@ class TypeComparer(initctx: Context) extends DotClass {
768768
isNewSubType(tp1.parent, tp2)
769769
}
770770
finally pendingRefinedBases = saved
771-
} || needsEtaLift(tp2, tp1) && isSubType(tp1, tp2.EtaLiftTo(tp1.typeParams))
771+
} || needsEtaLift(tp2, tp1) && tp2.testLifted(tp1.typeParams, isSubType(tp1, _))
772772
case AndType(tp11, tp12) =>
773773
isNewSubType(tp11, tp2) || isNewSubType(tp12, tp2)
774774
case _ =>

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import core._
66
import Types._, Contexts._, Flags._, Symbols._, Annotations._, Trees._, NameOps._
77
import Decorators._
88
import Variances._
9+
import config.Printers.variances
910

1011
/** Provides `check` method to check that all top-level definitions
1112
* in tree are variance correct. Does not recurse inside methods.
@@ -77,7 +78,7 @@ class VarianceChecker()(implicit ctx: Context) {
7778
* explicitly (their TypeDefs will be passed here.) For MethodTypes, the
7879
* same is true of the parameters (ValDefs).
7980
*/
80-
def apply(status: Option[VarianceError], tp: Type): Option[VarianceError] = ctx.traceIndented(s"variance checking $tp of $base at $variance") {
81+
def apply(status: Option[VarianceError], tp: Type): Option[VarianceError] = ctx.traceIndented(s"variance checking $tp of $base at $variance", variances) {
8182
if (status.isDefined) status
8283
else tp match {
8384
case tp: TypeRef =>

0 commit comments

Comments
 (0)