aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/TypeApplications.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-12-18 18:50:18 +0100
committerMartin Odersky <odersky@gmail.com>2015-12-18 18:50:40 +0100
commitd362455add3fcfb99d87c1e8290d9f6e1bf23654 (patch)
tree279b5cf47618b27783b3507297db52a3c863c7bb /src/dotty/tools/dotc/core/TypeApplications.scala
parent570cf0f84b0daa78a6234ead4b5b3c5b58b5db79 (diff)
downloaddotty-d362455add3fcfb99d87c1e8290d9f6e1bf23654.tar.gz
dotty-d362455add3fcfb99d87c1e8290d9f6e1bf23654.tar.bz2
dotty-d362455add3fcfb99d87c1e8290d9f6e1bf23654.zip
Fix higher-kinded unions and intersections
Since And/Or type themselves are parameterless, their the union and intersection of hgiher-kinded types has to be treated specially: The types have to be pulled under a common lambda.
Diffstat (limited to 'src/dotty/tools/dotc/core/TypeApplications.scala')
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala45
1 files changed, 45 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index fbab4ee39..9a12d2635 100644
--- a/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -173,8 +173,45 @@ object TypeApplications {
if (tparams.isEmpty) args
else args.zipWithConserve(tparams)((arg, tparam) => arg.etaExpandIfHK(tparam.infoOrCompleter))
+ /** The references `<rt>.this.$hk0, ..., <rt>.this.$hk<n-1>`. */
def argRefs(rt: RefinedType, n: Int)(implicit ctx: Context) =
List.range(0, n).map(i => RefinedThis(rt).select(tpnme.hkArg(i)))
+
+ /** Merge `tp1` and `tp2` under a common lambda, combining them with `op`.
+ * @param tparams1 The type parameters of `tp1`
+ * @param tparams2 The type parameters of `tp2`
+ * Produces the type lambda
+ *
+ * [v1 X1 B1, ..., vn Xn Bn] -> op(tp1[X1, ..., Xn], tp2[X1, ..., Xn])
+ *
+ * where
+ *
+ * - variances `vi` are the variances of corresponding type parameters for `tp1`
+ * or `tp2`, or are 0 of the latter disagree.
+ * - bounds `Bi` are the intersection of the corresponding type parameter bounds
+ * of `tp1` and `tp2`.
+ */
+ def hkCombine(tp1: Type, tp2: Type,
+ tparams1: List[TypeSymbol], tparams2: List[TypeSymbol], op: (Type, Type) => Type)
+ (implicit ctx: Context): Type = {
+ val variances = (tparams1, tparams2).zipped.map { (tparam1, tparam2) =>
+ val v1 = tparam1.variance
+ val v2 = tparam2.variance
+ if (v1 == v2) v1 else 0
+ }
+ val bounds: List[RefinedType => TypeBounds] =
+ (tparams1, tparams2).zipped.map { (tparam1, tparam2) =>
+ val b1: RefinedType => TypeBounds =
+ tp1.memberInfo(tparam1).bounds.internalizeFrom(tparams1)
+ val b2: RefinedType => TypeBounds =
+ tp2.memberInfo(tparam2).bounds.internalizeFrom(tparams2)
+ (rt: RefinedType) => b1(rt) & b2(rt)
+ }
+ val app1: RefinedType => Type = rt => tp1.appliedTo(argRefs(rt, tparams1.length))
+ val app2: RefinedType => Type = rt => tp2.appliedTo(argRefs(rt, tparams2.length))
+ val body = (rt: RefinedType) => op(app1(rt), app2(rt))
+ TypeLambda(variances, bounds, body)
+ }
}
import TypeApplications._
@@ -273,6 +310,14 @@ class TypeApplications(val self: Type) extends AnyVal {
false
}
+ /** Replace references to type parameters with references to hk arguments `this.$hk_i`
+ * Care is needed not to cause cyclic reference errors, hence `SafeSubstMap`.
+ */
+ private[TypeApplications] def internalizeFrom[T <: Type](tparams: List[Symbol])(implicit ctx: Context): RefinedType => T =
+ (rt: RefinedType) =>
+ new ctx.SafeSubstMap(tparams , argRefs(rt, tparams.length))
+ .apply(self).asInstanceOf[T]
+
/** Lambda abstract `self` with given type parameters. Examples:
*
* type T[X] = U becomes type T = [X] -> U