aboutsummaryrefslogtreecommitdiff
path: root/src/dotty
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-05-17 13:26:00 +0200
committerMartin Odersky <odersky@gmail.com>2015-05-21 17:41:14 +0200
commitff96f13f0fb7f69d6dd747908281373031b9c545 (patch)
treeb08c3b70f56032b0d561aecb4da63be8a8ab6565 /src/dotty
parent98ae292662828954c86652b42b7fd42fc2782cbc (diff)
downloaddotty-ff96f13f0fb7f69d6dd747908281373031b9c545.tar.gz
dotty-ff96f13f0fb7f69d6dd747908281373031b9c545.tar.bz2
dotty-ff96f13f0fb7f69d6dd747908281373031b9c545.zip
Fix isSubType bug related to testLifted
testLifted widened a type to an some base type constructor when comparing with a type lambda. This can return false positives if the widened type is on the right of the comparison. The fix adds a parameter to testLifted indicating whether widening is permitted.
Diffstat (limited to 'src/dotty')
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala9
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala7
2 files changed, 9 insertions, 7 deletions
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index 8bd1651dc..17f6a8209 100644
--- a/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -515,7 +515,8 @@ class TypeApplications(val self: Type) extends AnyVal {
self.appliedTo(tparams map (_.typeRef)).LambdaAbstract(tparams)
}
- /** Test whether this type has a base type `B[T1, ..., Tn]` where the type parameters
+ /** 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
*
@@ -525,7 +526,7 @@ class TypeApplications(val self: Type) extends AnyVal {
* 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.
*/
- def testLifted(tparams: List[Symbol], p: Type => Boolean)(implicit ctx: Context): Boolean = {
+ def testLifted(tparams: List[Symbol], p: Type => Boolean, canWiden: Boolean)(implicit ctx: Context): Boolean = {
def tryLift(bcs: List[ClassSymbol]): Boolean = bcs match {
case bc :: bcs1 =>
val tp = self.baseTypeWithArgs(bc)
@@ -548,7 +549,7 @@ class TypeApplications(val self: Type) extends AnyVal {
false
}
if (tparams.isEmpty) false
- else if (typeParams.nonEmpty) p(EtaExpand) || tryLift(self.baseClasses)
- else tryLift(self.baseClasses)
+ else if (typeParams.nonEmpty) p(EtaExpand) || canWiden && tryLift(self.baseClasses)
+ else canWiden && tryLift(self.baseClasses)
}
}
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index 18f9f08bb..95978dc32 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))
+ needsEtaLift(tp1, tp2) && tp1.testLifted(tp2.typeParams, isSubType(_, tp2), canWiden = true)
}
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, _))
+ needsEtaLift(tp2, tp1) && tp2.testLifted(tp1.typeParams, isSubType(tp1, _), canWiden = false)
case AndType(tp11, tp12) =>
eitherIsSubType(tp11, tp2, tp12, tp2)
case JavaArrayType(elem1) =>
@@ -475,7 +475,8 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
val lambda = projection.prefix.LambdaClass(forcing = true)
lambda.exists && !other.isLambda &&
other.testLifted(lambda.typeParams,
- if (inOrder) isSubType(projection.prefix, _) else isSubType(_, projection.prefix))
+ if (inOrder) isSubType(projection.prefix, _) else isSubType(_, projection.prefix),
+ canWiden = !inOrder)
}
/** Returns true iff either `tp11 <:< tp21` or `tp12 <:< tp22`, trying at the same time