aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-05-18 12:01:56 +0200
committerMartin Odersky <odersky@gmail.com>2015-05-21 17:41:15 +0200
commitd5975dc740bd55ea72477e9f726882edcd18dbe3 (patch)
tree53d9b9d1ba79ef61f60cc70ffb33bba87723875c
parent17f1c5fc26d2b1390ef5a224c8187dcc10ce0784 (diff)
downloaddotty-d5975dc740bd55ea72477e9f726882edcd18dbe3.tar.gz
dotty-d5975dc740bd55ea72477e9f726882edcd18dbe3.tar.bz2
dotty-d5975dc740bd55ea72477e9f726882edcd18dbe3.zip
Generaize canWiden to classBounds
This gives us a cheap way to bound the search of all baseclasses in testLifted.
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala18
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala9
2 files changed, 16 insertions, 11 deletions
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index 17f6a8209..7f3f8a446 100644
--- a/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -515,18 +515,19 @@ class TypeApplications(val self: Type) extends AnyVal {
self.appliedTo(tparams map (_.typeRef)).LambdaAbstract(tparams)
}
- /** Test whether this type if od the form `B[T1, ..., Tn]`, or,
- * if `canWiden` if true, has a base type of the form `B[T1, ..., Bn]` where the type parameters
- * of `B` match one-by-one the variances of `tparams`, and where the lambda
- * abstracted type
+ /** Test whether this type has a base type of the form `B[T1, ..., Bn]` 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 their occurrence in `baseClasses`.
* A type parameter matches a variance V if it has V as its variance or if V == 0.
+ * @param classBounds A hint to bound the search. Only types that derive from one of the
+ * classes in classBounds are considered.
*/
- def testLifted(tparams: List[Symbol], p: Type => Boolean, canWiden: Boolean)(implicit ctx: Context): Boolean = {
+ def testLifted(tparams: List[Symbol], p: Type => Boolean, classBounds: List[ClassSymbol])(implicit ctx: Context): Boolean = {
def tryLift(bcs: List[ClassSymbol]): Boolean = bcs match {
case bc :: bcs1 =>
val tp = self.baseTypeWithArgs(bc)
@@ -534,7 +535,8 @@ class TypeApplications(val self: Type) extends AnyVal {
val tycon = tp.withoutArgs(targs)
def variancesMatch(param1: Symbol, param2: Symbol) =
param2.variance == param2.variance || param2.variance == 0
- if ((tycon.typeParams corresponds tparams)(variancesMatch)) {
+ if (classBounds.exists(tycon.derivesFrom(_)) &&
+ tycon.typeParams.corresponds(tparams)(variancesMatch)) {
val expanded = tycon.EtaExpand
val lifted = (expanded /: targs) { (partialInst, targ) =>
val tparam = partialInst.typeParams.head
@@ -549,7 +551,7 @@ class TypeApplications(val self: Type) extends AnyVal {
false
}
if (tparams.isEmpty) false
- else if (typeParams.nonEmpty) p(EtaExpand) || canWiden && tryLift(self.baseClasses)
- else canWiden && tryLift(self.baseClasses)
+ else if (typeParams.nonEmpty) p(EtaExpand) || classBounds.nonEmpty && tryLift(self.baseClasses)
+ else classBounds.nonEmpty && tryLift(self.baseClasses)
}
}
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index 95978dc32..89c3958af 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -345,7 +345,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
|| fourthTry(tp1, tp2)
)
normalPath ||
- needsEtaLift(tp1, tp2) && tp1.testLifted(tp2.typeParams, isSubType(_, tp2), canWiden = true)
+ needsEtaLift(tp1, tp2) && tp1.testLifted(tp2.typeParams, isSubType(_, tp2), classBounds(tp2))
}
else // fast path, in particular for refinements resulting from parameterization.
isSubType(tp1, skipped2) &&
@@ -453,7 +453,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
isNewSubType(tp1.underlying.widenExpr, tp2) || comparePaths
case tp1: RefinedType =>
isNewSubType(tp1.parent, tp2) ||
- needsEtaLift(tp2, tp1) && tp2.testLifted(tp1.typeParams, isSubType(tp1, _), canWiden = false)
+ needsEtaLift(tp2, tp1) && tp2.testLifted(tp1.typeParams, isSubType(tp1, _), Nil)
case AndType(tp11, tp12) =>
eitherIsSubType(tp11, tp2, tp12, tp2)
case JavaArrayType(elem1) =>
@@ -476,9 +476,12 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
lambda.exists && !other.isLambda &&
other.testLifted(lambda.typeParams,
if (inOrder) isSubType(projection.prefix, _) else isSubType(_, projection.prefix),
- canWiden = !inOrder)
+ if (inOrder) Nil else classBounds(projection.prefix))
}
+ /** The class symbols bounding the type of the `Apply` member of `tp` */
+ private def classBounds(tp: Type) = tp.member(tpnme.Apply).info.classSymbols
+
/** Returns true iff either `tp11 <:< tp21` or `tp12 <:< tp22`, trying at the same time
* to keep the constraint as wide as possible. Specifically, if
*