aboutsummaryrefslogtreecommitdiff
path: root/src/dotty
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty')
-rw-r--r--src/dotty/tools/dotc/core/Types.scala81
-rw-r--r--src/dotty/tools/dotc/core/pickling/UnPickler.scala17
2 files changed, 60 insertions, 38 deletions
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 71a7e555c..71c2ce5de 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -232,6 +232,7 @@ object Types {
* type parameters of the HigherKinded class.
* For a refinement type, the type parameters of its parent, unless there's a
* refinement with the same name. Inherited by all other type proxies.
+ * For an intersection type A & B, the type parameters of its left operand, A.
* Empty list for all other types.
*/
final def typeParams(implicit ctx: Context): List[TypeSymbol] = this match {
@@ -251,6 +252,8 @@ object Types {
tp.parent.typeParams filterNot (_.name == tp.refinedName)
case tp: TypeProxy =>
tp.underlying.typeParams
+ case tp: AndType =>
+ tp.tp1.typeParams
case _ =>
Nil
}
@@ -656,7 +659,7 @@ object Types {
case tp: TypeProxy =>
tp.underlying.appliedTo(args)
case AndType(l, r) =>
- l.appliedTo(args) & r.appliedTo(args)
+ l.appliedTo(args) & r
}
}
@@ -754,43 +757,49 @@ object Types {
* Occurrences of `X` are rewritten to `this.T2` and the whole definition becomes:
*
* type A = Triple { type T1 = (this.T2, this.T2); type T3 = String }
+ *
+ * If the RHS is an intersection type A & B, we Lambda abstract on A instead and
+ * then recombine with & B.
*/
- def LambdaAbstract(boundSyms: List[Symbol])(error: (String, Position) => Unit)(implicit ctx: Context): Type = {
- val cls = typeSymbol
- if (!cls.isClass)
- error("right-hand side of parameterized alias type must be a class", cls.pos)
-
- /** Rewrite type.
- * @param tp The type to rewrite
- * @param symMap A map that associates bound symbols were seen to match a rhs type argument
- * with the corresponding parameter reference (where the refined this is left open).
- * @return The rewritten type, paired with
- * the list of replacement types for bound symbols, parameterized by the actual refinement
- */
- def rewrite(tp: Type, symMap: Map[Symbol, RefinedType => Type]): (Type, RefinedType => List[Type]) = tp match {
- case tp @ RefinedType(parent, name: TypeName) =>
- tp.refinedInfo match {
- case tr: TypeRef if boundSyms contains tr.symbol =>
- rewrite(tp.parent, symMap + (tr.symbol -> (rt => TypeRef(RefinedThis(rt), name))))
- case info =>
- val (parent1, replacements) = rewrite(tp.parent, symMap)
- (RefinedType(parent1, name, rt => info.subst(boundSyms, replacements(rt))),
- replacements)
- }
- case tp =>
- def replacements(rt: RefinedType): List[Type] =
- for (sym <- boundSyms) yield {
- symMap get sym match {
- case Some(replacement) =>
- replacement(rt)
- case None =>
- error(s"parameter $sym of type alias does not appear as type argument of the aliased $cls", sym.pos)
- defn.AnyType
- }
+ def LambdaAbstract(boundSyms: List[Symbol])(error: (String, Position) => Unit)(implicit ctx: Context): Type = this match {
+ case AndType(l, r) =>
+ AndType(l.LambdaAbstract(boundSyms)(error), r)
+ case _ =>
+ val cls = typeSymbol
+ if (!cls.isClass)
+ error("right-hand side of parameterized alias type must refer to a class", cls.pos)
+
+ val correspondingParamName: Map[Symbol, TypeName] = {
+ for { (tparam, targ: TypeRef) <- cls.typeParams zip typeArgs
+ if boundSyms contains targ.symbol
+ } yield targ.symbol -> tparam.name
+ }.toMap
+
+ val correspondingNames = correspondingParamName.values.toSet
+
+ def replacements(rt: RefinedType): List[Type] =
+ for (sym <- boundSyms) yield {
+ correspondingParamName get sym match {
+ case Some(name) =>
+ TypeRef(RefinedThis(rt), name)
+ case None =>
+ error(s"parameter $sym of type alias does not appear as type argument of the aliased $cls", sym.pos)
+ defn.AnyType
}
- (tp, replacements)
- }
- rewrite(this, Map())._1
+ }
+
+ def rewrite(tp: Type): Type = tp match {
+ case tp @ RefinedType(parent, name: TypeName) =>
+ if (correspondingNames contains name) rewrite(parent)
+ else RefinedType(
+ rewrite(parent),
+ name,
+ rt => tp.refinedInfo.subst(boundSyms, replacements(rt)))
+ case tp =>
+ tp
+ }
+
+ rewrite(this)
}
// ----- misc -----------------------------------------------------------
diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
index f35c24fd7..ea42b40a4 100644
--- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
@@ -44,8 +44,21 @@ object UnPickler {
*/
def depoly(tp: Type, denot: SymDenotation)(implicit ctx: Context): Type = tp match {
case TempPolyType(tparams, restpe) =>
- if (denot.isAbstractType) restpe.bounds.higherKinded(tparams)
- else PolyType.fromSymbols(tparams, restpe)
+ if (denot.isAbstractType)
+ restpe.bounds.higherKinded(tparams)
+ else if (denot.isAliasType) {
+ var err: Option[(String, Position)] = None
+ val result = restpe.LambdaAbstract(tparams) { (msg, pos) => err = Some((msg, pos)) }
+ for ((msg, pos) <- err)
+ ctx.warning(
+ s"""$msg
+ |originally parsed type : ${tp.show}
+ |will be approximated by: ${result.show}.
+ |Proceed at own risk.""".stripMargin)
+ result
+ }
+ else
+ PolyType.fromSymbols(tparams, restpe)
case tp => tp
}