From 830e511b6b620716d3f550a199d0a5c52c95423a Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 18 Mar 2013 12:05:52 +0100 Subject: Cleanup of higher-kinded types treatment --- src/dotty/tools/dotc/core/Definitions.scala | 9 +++--- src/dotty/tools/dotc/core/TypeComparers.scala | 16 +++++------ src/dotty/tools/dotc/core/pickling/UnPickler.scala | 33 ++++++++++++++++------ 3 files changed, 38 insertions(+), 20 deletions(-) (limited to 'src/dotty/tools') 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 -- cgit v1.2.3