diff options
author | Martin Odersky <odersky@gmail.com> | 2013-03-18 22:05:26 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2013-03-18 22:05:26 +0100 |
commit | eb2b6bf420b24ac0307e17fc9fec38e91012d1af (patch) | |
tree | a49d5b4f45f78ec96006b18816b69ed30c8a745e /src/dotty/tools/dotc/core/Types.scala | |
parent | 830e511b6b620716d3f550a199d0a5c52c95423a (diff) | |
download | dotty-eb2b6bf420b24ac0307e17fc9fec38e91012d1af.tar.gz dotty-eb2b6bf420b24ac0307e17fc9fec38e91012d1af.tar.bz2 dotty-eb2b6bf420b24ac0307e17fc9fec38e91012d1af.zip |
More changes for higher-kinded types emulation.
Diffstat (limited to 'src/dotty/tools/dotc/core/Types.scala')
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 54 |
1 files changed, 48 insertions, 6 deletions
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 690f0f476..2c7037a75 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -6,6 +6,7 @@ import Symbols._ import TypeComparers._ import Flags._ import Names._ +import StdNames._, NameOps._ import Scopes._ import Constants._ import Contexts._ @@ -76,6 +77,9 @@ object Types { /** Is this type different from NoType? */ def exists: Boolean = true + /** This type, if it exists, otherwise `that` type */ + def orElse(that: => Type) = if (exists) this else that + /** Is this type a value type? */ final def isValueType: Boolean = this.isInstanceOf[ValueType] @@ -522,10 +526,11 @@ object Types { /** Encode the type resulting from applying this type to given arguments */ final def appliedTo(args: List[Type])(implicit ctx: Context): Type = { + def recur(tp: Type, tparams: List[TypeSymbol], args: List[Type]): Type = args match { case arg :: args1 => if (tparams.isEmpty) { - println(s"applied type mismatch: $this $args, $typeParams = typeParams") + println(s"applied type mismatch: $this $args, $typeParams = typeParams") // !!! DEBUG println(s"precomplete decls = ${typeSymbol.preCompleteDecls.toList.map(_.denot).mkString("\n ")}") } val tparam = tparams.head @@ -533,12 +538,47 @@ object Types { recur(tp1, tparams.tail, args1) case nil => tp } + + def hkApp(tp: Type): Type = tp match { + case AndType(l, r) => + hkApp(l) orElse hkApp(r) + case tp: RefinedType if defn.hkTraits contains tp.typeSymbol => + tp + case tp: TypeProxy => + hkApp(tp.underlying) + } + + def hkRefinement(tp: TypeRef): Type = { + val hkArgs = hkApp(tp.info).typeArgs + ((tp: Type) /: hkArgs.zipWithIndex.zip(args)) { + case (parent, ((hkArg, idx), arg)) => + val vsym = hkArg.typeSymbol + val rhs = + if (vsym == defn.InvariantBetweenClass) + TypeAlias(arg) + else if (vsym == defn.CovariantBetweenClass) + TypeBounds.upper(arg) + else { + assert(vsym == defn.ContravariantBetweenClass) + TypeBounds.lower(arg) + } + RefinedType(parent, tpnme.higherKindedParamName(idx), rhs) + } + } + + // begin applied type if (args.isEmpty) this else this match { case tp: PolyType => tp.instantiate(args) - case tp: TypeRef if tp.symbol.isClass => - recur(tp, tp.typeParams, args) + case tp: TypeRef => + val tsym = tp.symbol + if (tsym.isClass) + recur(tp, tp.typeParams, args) + else if (tsym.isAliasType) + tp.underlying.appliedTo(args) + else + hkRefinement(tp) case tp: TypeProxy => tp.underlying.appliedTo(args) } @@ -1009,10 +1049,9 @@ object Types { def derivedRefinedType(parent: Type, refinedName: Name, refinedInfo: Type)(implicit ctx: Context): RefinedType = if ((parent eq this.parent) && (refinedName eq this.refinedName) && (refinedInfo eq this.refinedInfo)) this - else if ((defn.hkParamNames contains refinedName) && - (parent.typeParams.length >= defn.hkParamArity(refinedName))) + else if (refinedName.isHkParamName && typeParams.length > refinedName.hkParamIndex) derivedRefinedType( - parent, parent.typeParams.apply(defn.hkParamArity(refinedName)).name, refinedInfo) + parent, parent.typeParams.apply(refinedName.hkParamIndex).name, refinedInfo) else RefinedType(parent, refinedName, rt => refinedInfo.substThis(this, RefinedThis(rt))) @@ -1337,6 +1376,9 @@ object Types { TypeBounds(f(lo), f(hi)) override def computeHash = doHash(lo, hi) + + override def toString = + if (lo eq hi) s"TypeAlias($lo)" else s"TypeBounds($lo, $hi)" } final class CachedTypeBounds(lo: Type, hi: Type) extends TypeBounds(lo, hi) |