aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-03-18 12:05:52 +0100
committerMartin Odersky <odersky@gmail.com>2013-03-18 12:05:52 +0100
commit830e511b6b620716d3f550a199d0a5c52c95423a (patch)
tree01de8964bc3a97cb2ff5fe4d11c635ec7e709f36 /src
parent52d740d120cd197ee816aa0a06732ccdb5d5ab29 (diff)
downloaddotty-830e511b6b620716d3f550a199d0a5c52c95423a.tar.gz
dotty-830e511b6b620716d3f550a199d0a5c52c95423a.tar.bz2
dotty-830e511b6b620716d3f550a199d0a5c52c95423a.zip
Cleanup of higher-kinded types treatment
Diffstat (limited to 'src')
-rw-r--r--src/dotty/tools/dotc/core/Definitions.scala9
-rw-r--r--src/dotty/tools/dotc/core/TypeComparers.scala16
-rw-r--r--src/dotty/tools/dotc/core/pickling/UnPickler.scala33
3 files changed, 38 insertions, 20 deletions
diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala
index 471510e6f..c728493dd 100644
--- a/src/dotty/tools/dotc/core/Definitions.scala
+++ b/src/dotty/tools/dotc/core/Definitions.scala
@@ -211,15 +211,16 @@ class Definitions(implicit ctx: Context) {
def hkParamNames = _hkParamNames
def hkParamArity = _hkParamArity
+ /** A trait `HigherKinded[Lo_1,...,Lo_n,Hi_1,...,Hi_n]` that represents
+ * the bounds of a higher-kinded type.
+ */
def hkTrait(n: Int): ClassSymbol = {
val completer = new LazyType {
def complete(denot: SymDenotation): Unit = {
val cls = denot.asClass.classSymbol
val paramDecls = newScope
- for (i <- 0 until n) {
- newSyntheticTypeParam(cls, paramDecls, "Lo"+i)
- newSyntheticTypeParam(cls, paramDecls, "Hi"+i)
- }
+ for (i <- 0 until n) newSyntheticTypeParam(cls, paramDecls, "Lo"+i)
+ for (i <- 0 until n) newSyntheticTypeParam(cls, paramDecls, "Hi"+i)
denot.info = ClassInfo(ScalaPackageClass.thisType, cls, List(ObjectClass.typeConstructor), paramDecls)
}
}
diff --git a/src/dotty/tools/dotc/core/TypeComparers.scala b/src/dotty/tools/dotc/core/TypeComparers.scala
index d3c00e818..cdc9016cb 100644
--- a/src/dotty/tools/dotc/core/TypeComparers.scala
+++ b/src/dotty/tools/dotc/core/TypeComparers.scala
@@ -205,15 +205,15 @@ object TypeComparers {
*/
def isSubTypeHK(tp1: Type, tp2: Type): Boolean = {
val tparams = tp1.typeParams
- val hkargs = tp2.typeArgs
- def toBounds(args: List[Type]): List[TypeBounds] = (args: @unchecked) match {
- case lo :: hi :: args1 => TypeBounds(lo, hi) :: toBounds(args1)
- case Nil => Nil
+ val hkArgs = tp2.typeArgs
+ val (loBounds, hiBounds) = hkArgs splitAt (hkArgs.length / 2)
+ (loBounds.length == tparams.length) && {
+ val base = ctx.newSkolemSingleton(tp1)
+ (loBounds, hiBounds, tparams).zipped.forall { (lo, hi, tparam) =>
+ val tparamBounds = base.memberInfo(tparam).bounds
+ lo <:< tparamBounds.lo && tparamBounds.hi <:< hi
+ }
}
- val base = ctx.newSkolemSingleton(tp1)
- val hkbounds = toBounds(hkargs)
- (hkbounds.length == tparams.length) &&
- (hkbounds, tparams map (base.memberInfo(_).bounds)).zipped.forall(_ contains _)
}
/** A function implementing `tp1` matches `tp2`. */
diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
index d4e27f11a..ddbc4b8e2 100644
--- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
@@ -29,21 +29,38 @@ object UnPickler {
/** Temporary type for classinfos, will be decomposed on completion of the class */
case class TempClassInfoType(parentTypes: List[Type], decls: MutableScope, clazz: Symbol) extends UncachedGroundType
+ /** Convert temp poly type to some native Dotty idiom.
+ * @param forSym The symbol that gets the converted type as info.
+ * If `forSym` is not an abstract type, this simply returns an equivalent `PolyType`.
+ * If `forSym` is an abstract type, it converts a
+ *
+ * TempPolyType(List(T_1, ..., T_n), lo..hi)
+ *
+ * to
+ *
+ * Bottom..HigherKinded[lo_1, ..., lo_N, hi_1, ..., hi_N] & (lo..hi)
+ *
+ * where lo_i, hi_i are the lower/upper bounds of the type parameters T_i.
+ * This works only as long as none of the type parameters T_i appears in any
+ * of the bounds or the result type. Such occurrences of type parameters are
+ * replaced by Any, and a warning is issued in this case.
+ */
def depoly(tp: Type, forSym: SymDenotation)(implicit ctx: Context): Type = tp match {
case TempPolyType(tparams, restpe) =>
if (forSym.isAbstractType) {
- val typeArgs = tparams flatMap { tparam =>
- List(tparam.info.bounds.lo, tparam.info.bounds.hi)
- }
- val correctedArgs = typeArgs.mapConserve(
- _.subst(tparams, tparams map (_ => defn.AnyType)))
+ val typeArgs = (tparams map (_.info.bounds.lo)) ++ (tparams map (_.info.bounds.hi))
+ val elimTparams: Type => Type = _.subst(tparams, tparams map (_ => defn.AnyType))
+ val correctedArgs = typeArgs.mapConserve(elimTparams)
+ val correctedRes = elimTparams(restpe)
+ assert(correctedRes.isInstanceOf[TypeBounds])
val hk = defn.hkTrait(tparams.length)
- if (typeArgs ne correctedArgs)
+ val result = TypeBounds.upper(hk.typeConstructor.appliedTo(correctedArgs)) & correctedRes
+ if ((typeArgs ne correctedArgs) || (restpe ne correctedRes))
ctx.warning(s"""failure to import F-bounded higher-kinded type
|original type definition: ${forSym.show}${tp.show}
- |definition used instead : ${forSym.show} <: $hk[${correctedArgs.map(_.show).mkString(", ")}]
+ |definition used instead : ${forSym.show}${result.show}
|proceed at own risk.""".stripMargin)
- hk.typeConstructor.appliedTo(typeArgs)
+ result
} else
PolyType.fromSymbols(tparams, restpe)
case tp => tp