aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/TypeApplications.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools/dotc/core/TypeApplications.scala')
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala80
1 files changed, 66 insertions, 14 deletions
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index e854e672f..b4c30d902 100644
--- a/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -12,6 +12,29 @@ import Flags._
import util.Positions.Position
import collection.mutable
+object TypeApplications {
+
+ /** Assert type is not a TypeBounds instance and return it unchanged */
+ val noBounds = (tp: Type) => tp match {
+ case tp: TypeBounds => throw new AssertionError("no TypeBounds allowed")
+ case _ => tp
+ }
+
+ /** If `tp` is a TypeBounds instance return its lower bound else return `tp` */
+ val boundsToLo = (tp: Type) => tp match {
+ case tp: TypeBounds => tp.lo
+ case _ => tp
+ }
+
+ /** If `tp` is a TypeBounds instance return its upper bound else return `tp` */
+ val boundsToHi = (tp: Type) => tp match {
+ case tp: TypeBounds => tp.hi
+ case _ => tp
+ }
+}
+
+import TypeApplications._
+
/** A decorator that provides methods for modeling type application */
class TypeApplications(val self: Type) extends AnyVal {
@@ -135,24 +158,43 @@ class TypeApplications(val self: Type) extends AnyVal {
else TypeAlias(self, v)
}
- /** The type arguments of the base type instance wrt `base` of this type */
- final def baseTypeArgs(base: Symbol)(implicit ctx: Context): List[Type] =
+ /** The type arguments of this type's base type instance wrt.`base`.
+ * Existential types in arguments are returned as TypeBounds instances.
+ */
+ final def baseArgInfos(base: Symbol)(implicit ctx: Context): List[Type] =
if (self derivesFrom base)
- base.typeParams map (param => self.member(param.name).info.argType(param))
+ base.typeParams map (param => self.member(param.name).info.argInfo(param))
else
Nil
+ /** The type arguments of this type's base type instance wrt.`base`.
+ * Existential types in arguments are disallowed.
+ */
+ final def baseArgTypes(base: Symbol)(implicit ctx: Context): List[Type] = baseArgInfos(base) mapConserve noBounds
+
+ /** The type arguments of this type's base type instance wrt.`base`.
+ * Existential types in arguments are approximanted by their lower bound.
+ */
+ final def baseArgTypesLo(base: Symbol)(implicit ctx: Context): List[Type] = baseArgInfos(base) mapConserve boundsToLo
+
+ /** The type arguments of this type's base type instance wrt.`base`.
+ * Existential types in arguments are approximanted by their upper bound.
+ */
+ final def baseArgTypesHi(base: Symbol)(implicit ctx: Context): List[Type] = baseArgInfos(base) mapConserve boundsToHi
+
/** The first type argument of the base type instance wrt `base` of this type */
- final def firstBaseTypeArg(base: Symbol)(implicit ctx: Context): Type = base.typeParams match {
+ final def firstBaseArgInfo(base: Symbol)(implicit ctx: Context): Type = base.typeParams match {
case param :: _ if self derivesFrom base =>
- self.member(param.name).info.argType(param)
+ self.member(param.name).info.argInfo(param)
case _ =>
NoType
}
- /** The base type including all type arguments of this type */
+ /** The base type including all type arguments of this type.
+ * Existential types in arguments are returned as TypeBounds instances.
+ */
final def baseTypeWithArgs(base: Symbol)(implicit ctx: Context): Type =
- self.baseTypeRef(base).appliedTo(baseTypeArgs(base))
+ self.baseTypeRef(base).appliedTo(baseArgInfos(base))
/** Translate a type of the form From[T] to To[T], keep other types as they are.
* `from` and `to` must be static classes, both with one type parameter, and the same variance.
@@ -163,9 +205,10 @@ class TypeApplications(val self: Type) extends AnyVal {
else self
/** If this is an encoding of a (partially) applied type, return its arguments,
- * otherwise return Nil
+ * otherwise return Nil.
+ * Existential types in arguments are returned as TypeBounds instances.
*/
- final def typeArgs(implicit ctx: Context): List[Type] = {
+ final def argInfos(implicit ctx: Context): List[Type] = {
var tparams: List[TypeSymbol] = null
def recur(tp: Type, refineCount: Int): mutable.ListBuffer[Type] = tp.stripTypeVar match {
case tp @ RefinedType(tycon, name) =>
@@ -175,7 +218,7 @@ class TypeApplications(val self: Type) extends AnyVal {
if (tparams == null) tparams = tycon.typeParams
if (buf.size < tparams.length) {
val tparam = tparams(buf.size)
- if (name == tparam.name) buf += tp.refinedInfo.argType(tparam)
+ if (name == tparam.name) buf += tp.refinedInfo.argInfo(tparam)
else null
} else null
}
@@ -187,6 +230,15 @@ class TypeApplications(val self: Type) extends AnyVal {
if (buf == null) Nil else buf.toList
}
+ /** Argument types where existential types in arguments are disallowed */
+ def argTypes(implicit ctx: Context) = argInfos mapConserve noBounds
+
+ /** Argument types where existential types in arguments are approximated by their lower bound */
+ def argTypesLo(implicit ctx: Context) = argInfos mapConserve boundsToLo
+
+ /** Argument types where existential types in arguments are approximated by their upper bound */
+ def argTypesHi(implicit ctx: Context) = argInfos mapConserve boundsToHi
+
/** The core type without any type arguments.
* @param `typeArgs` must be the type arguments of this type.
*/
@@ -201,7 +253,7 @@ class TypeApplications(val self: Type) extends AnyVal {
/** If this is the image of a type argument to type parameter `tparam`,
* recover the type argument, otherwise NoType.
*/
- final def argType(tparam: Symbol)(implicit ctx: Context): Type = self match {
+ final def argInfo(tparam: Symbol)(implicit ctx: Context): Type = self match {
case TypeBounds(lo, hi) =>
if (lo eq hi) hi
else {
@@ -216,7 +268,7 @@ class TypeApplications(val self: Type) extends AnyVal {
/** The element type of a sequence or array */
def elemType(implicit ctx: Context): Type =
- firstBaseTypeArg(defn.SeqClass) orElse firstBaseTypeArg(defn.ArrayClass)
+ firstBaseArgInfo(defn.SeqClass) orElse firstBaseArgInfo(defn.ArrayClass)
/** If this type is of the normalized form Array[...[Array[T]...]
* return the number of Array wrappers and T.
@@ -225,7 +277,7 @@ class TypeApplications(val self: Type) extends AnyVal {
final def splitArray(implicit ctx: Context): (Int, Type) = {
def recur(n: Int, tp: Type): (Int, Type) = tp.stripTypeVar match {
case RefinedType(tycon, _) if tycon isRef defn.ArrayClass =>
- tp.typeArgs match {
+ tp.argInfos match {
case arg :: Nil => recur(n + 1, arg)
case _ => (n, tp)
}
@@ -274,7 +326,7 @@ class TypeApplications(val self: Type) extends AnyVal {
val correspondingParamName: Map[Symbol, TypeName] = {
for {
- (tparam, targ: TypeRef) <- cls.typeParams zip typeArgs
+ (tparam, targ: TypeRef) <- cls.typeParams zip argInfos
if boundSyms contains targ.symbol
} yield targ.symbol -> tparam.name
}.toMap