diff options
author | Martin Odersky <odersky@gmail.com> | 2015-05-18 12:01:56 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2015-05-21 17:41:15 +0200 |
commit | d5975dc740bd55ea72477e9f726882edcd18dbe3 (patch) | |
tree | 53d9b9d1ba79ef61f60cc70ffb33bba87723875c | |
parent | 17f1c5fc26d2b1390ef5a224c8187dcc10ce0784 (diff) | |
download | dotty-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.scala | 18 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeComparer.scala | 9 |
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 * |