aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/TypeComparer.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-03-25 10:45:26 +0100
committerMartin Odersky <odersky@gmail.com>2016-03-30 09:51:03 +0200
commit506c10613a4f5223472f76226c37cad1701e9610 (patch)
tree31caa446c8ae6c3be8be34e531b273d1d7fa2d58 /src/dotty/tools/dotc/core/TypeComparer.scala
parentc03c8ca068b61bc7cee97dbc9e183bb3e410b839 (diff)
downloaddotty-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/dotty/tools/dotc/core/TypeComparer.scala')
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala18
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)
}