diff options
author | Martin Odersky <odersky@gmail.com> | 2015-05-17 13:26:00 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2015-05-21 17:41:14 +0200 |
commit | ff96f13f0fb7f69d6dd747908281373031b9c545 (patch) | |
tree | b08c3b70f56032b0d561aecb4da63be8a8ab6565 /src/dotty/tools/dotc/core | |
parent | 98ae292662828954c86652b42b7fd42fc2782cbc (diff) | |
download | dotty-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/tools/dotc/core')
-rw-r--r-- | src/dotty/tools/dotc/core/TypeApplications.scala | 9 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeComparer.scala | 7 |
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 |