diff options
author | Martin Odersky <odersky@gmail.com> | 2016-03-25 10:45:26 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2016-03-30 09:51:03 +0200 |
commit | 506c10613a4f5223472f76226c37cad1701e9610 (patch) | |
tree | 31caa446c8ae6c3be8be34e531b273d1d7fa2d58 /src | |
parent | c03c8ca068b61bc7cee97dbc9e183bb3e410b839 (diff) | |
download | dotty-506c10613a4f5223472f76226c37cad1701e9610.tar.gz dotty-506c10613a4f5223472f76226c37cad1701e9610.tar.bz2 dotty-506c10613a4f5223472f76226c37cad1701e9610.zip |
Don't lambda expand and/or types over named type parameters
Do it only if at least one of the types has unnamed parameters. This is
a fundamental conflict with how we deal with intersections and unions.
Diffstat (limited to 'src')
-rw-r--r-- | src/dotty/tools/dotc/core/TypeComparer.scala | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala index 4e7a4a75d..833adf008 100644 --- a/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/src/dotty/tools/dotc/core/TypeComparer.scala @@ -1075,15 +1075,29 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { } } - /** `op(tp1, tp2)` unless `tp1` and `tp2` are type-constructors. + /** `op(tp1, tp2)` unless `tp1` and `tp2` are type-constructors with at least + * some unnamed type parameters. * In the latter case, combine `tp1` and `tp2` under a type lambda like this: * * [X1, ..., Xn] -> op(tp1[X1, ..., Xn], tp2[X1, ..., Xn]) + * + * Note: There is a tension between named and positional parameters here, which + * is impossible to resolve completely. Say you have + * + * C[type T], D[type U] + * + * Then do you expand `C & D` to `[T, U] -> C[T, U] & D[T, U]` or not? Under the named + * type parameter interpretation, this would be wrong whereas under the traditional + * higher-kinded interpretation this would be required. The problem arises from + * allowing both interpretations. A possible remedy is to be somehow stricter + * in where we allow which interpretation. */ private def liftIfHK(tp1: Type, tp2: Type, op: (Type, Type) => Type) = { val tparams1 = tp1.typeParams val tparams2 = tp2.typeParams - if (tparams1.isEmpty || tparams2.isEmpty) op(tp1, tp2) + def onlyNamed(tparams: List[TypeSymbol]) = tparams.forall(!_.is(ExpandedName)) + if (tparams1.isEmpty || tparams2.isEmpty || + onlyNamed(tparams1) && onlyNamed(tparams2)) op(tp1, tp2) else if (tparams1.length != tparams2.length) mergeConflict(tp1, tp2) else hkCombine(tp1, tp2, tparams1, tparams2, op) } |