diff options
author | Martin Odersky <odersky@gmail.com> | 2016-07-15 10:30:30 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2016-07-15 10:30:30 +0200 |
commit | 894c9fbf247765041fc32788c78b85f1b2b2a191 (patch) | |
tree | aa918254e5b9869e10af3e967f980fd458e4c309 /src | |
parent | a737b47a92fe414a5e7f07bae171878c81bf9f45 (diff) | |
download | dotty-894c9fbf247765041fc32788c78b85f1b2b2a191.tar.gz dotty-894c9fbf247765041fc32788c78b85f1b2b2a191.tar.bz2 dotty-894c9fbf247765041fc32788c78b85f1b2b2a191.zip |
Bounds of type lambdas compare contravariantly
Enable checking of bounds when comparing type lambdas. This invalidates
a pattern used in t2994 and potentially other code, where a bound [X] -> Any
is used as a template that is a legal supertype of all other bounds. The old
behavior is still available under language:Scala2.
Diffstat (limited to 'src')
-rw-r--r-- | src/dotty/tools/dotc/core/TypeComparer.scala | 30 |
1 files changed, 18 insertions, 12 deletions
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala index 31cc87b3a..a895db178 100644 --- a/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/src/dotty/tools/dotc/core/TypeComparer.scala @@ -386,22 +386,28 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { case tp2 @ TypeLambda(tparams2, body2) => def compareHkLambda: Boolean = tp1.stripTypeVar match { case tp1 @ TypeLambda(tparams1, body1) => - // Don't compare bounds of lambdas, or t2994 will fail - // The issue is that, logically, bounds should compare contravariantly, - // so the bounds checking should look like this: - // - // tparams1.corresponds(tparams2)((tparam1, tparam2) => - // isSubType(tparam2.paramBounds.subst(tp2, tp1), tparam1.paramBounds)) - // - // But that would invalidate a pattern such as - // `[X0 <: Number] -> Number <:< [X0] -> Any` - // This wpuld mean that there is no convenient means anymore to express a kind - // as a supertype. The fix is to delay the checking of bounds so that only - // bounds of * types are checked. + /* Don't compare bounds of lambdas under language:Scala2, or t2994 will fail + * The issue is that, logically, bounds should compare contravariantly, + * but that would invalidate a pattern exploited in t2994: + * + * [X0 <: Number] -> Number <:< [X0] -> Any + * + * Under the new scheme, `[X0] -> Any` is NOT a kind that subsumes + * all other bounds. You'd have to write `[X0 >: Any <: Nothing] -> Any` instead. + * This might look weird, but is the only logically correct way to do it. + * + * Note: it would be nice if this could trigger a migration warning, but I + * am not sure how, since the code is buried so deep in subtyping logic. + */ + def boundsOK = + ctx.scala2Mode || + tparams1.corresponds(tparams2)((tparam1, tparam2) => + isSubType(tparam2.paramBounds.subst(tp2, tp1), tparam1.paramBounds)) val saved = comparingLambdas comparingLambdas = true try variancesConform(tparams1, tparams2) && + boundsOK && isSubType(body1, body2.subst(tp2, tp1)) finally comparingLambdas = saved case _ => |