aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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)
}