diff options
Diffstat (limited to 'src/dotty/tools/dotc/core/TypeApplications.scala')
-rw-r--r-- | src/dotty/tools/dotc/core/TypeApplications.scala | 80 |
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 |