aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/TypeApplications.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-03-25 10:34:54 +0100
committerMartin Odersky <odersky@gmail.com>2016-03-30 09:51:03 +0200
commitd0f9848486be2c8cec61acb94a592e8c9d4f842f (patch)
tree788bbed18e395c71eb2374c543b2cd6c2eff866d /src/dotty/tools/dotc/core/TypeApplications.scala
parent0474de635bee32f6d78726072230c9d572de0d52 (diff)
downloaddotty-d0f9848486be2c8cec61acb94a592e8c9d4f842f.tar.gz
dotty-d0f9848486be2c8cec61acb94a592e8c9d4f842f.tar.bz2
dotty-d0f9848486be2c8cec61acb94a592e8c9d4f842f.zip
Add methods for expressing named type params
Add methods for expressing what the named type parameters of a class or type are. Also, add a method that widens a type so that is has a specified set of named type parameters.
Diffstat (limited to 'src/dotty/tools/dotc/core/TypeApplications.scala')
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala60
1 files changed, 60 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index 8f8a7dbdd..817aaee15 100644
--- a/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -273,6 +273,66 @@ class TypeApplications(val self: Type) extends AnyVal {
}
}
+ /** The named type parameters declared or inherited by this type.
+ * These are all uninstantiated named type parameters of this type or one
+ * of its base types.
+ */
+ final def namedTypeParams(implicit ctx: Context): Set[TypeSymbol] = self match {
+ case self: ClassInfo =>
+ self.cls.namedTypeParams
+ case self: RefinedType =>
+ self.parent.namedTypeParams.filterNot(_.name == self.refinedName)
+ case self: SingletonType =>
+ Set()
+ case self: TypeProxy =>
+ self.underlying.namedTypeParams
+ case _ =>
+ Set()
+ }
+
+ /** The smallest supertype of this type that instantiated none of the named type parameters
+ * in `params`. That is, for each named type parameter `p` in `params`, either there is
+ * no type field named `p` in this type, or `p` is a named type parameter of this type.
+ * The first case is important for the recursive case of AndTypes, because some of their operands might
+ * be missing the named parameter altogether, but the AndType as a whole can still
+ * contain it.
+ */
+ final def widenToNamedTypeParams(params: Set[TypeSymbol])(implicit ctx: Context): Type = {
+
+ /** Is widening not needed for `tp`? */
+ def isOK(tp: Type) = {
+ val ownParams = tp.namedTypeParams
+ def isMissingOrOpen(param: TypeSymbol) = {
+ val ownParam = tp.nonPrivateMember(param.name).symbol
+ !ownParam.exists || ownParams.contains(ownParam.asType)
+ }
+ params.forall(isMissingOrOpen)
+ }
+
+ /** Widen type by forming the intersection of its widened parents */
+ def widenToParents(tp: Type) = {
+ val parents = tp.parents.map(p => tp.baseTypeWithArgs(p.symbol))
+ ctx.typeComparer.glb(parents.map(_.widenToNamedTypeParams(params)))
+ }
+
+ if (isOK(self)) self
+ else self match {
+ case self @ AppliedType(tycon, args) if !isOK(tycon) =>
+ widenToParents(self)
+ case self: TypeRef if self.symbol.isClass =>
+ widenToParents(self)
+ case self: RefinedType =>
+ val parent1 = self.parent.widenToNamedTypeParams(params)
+ if (params.exists(_.name == self.refinedName)) parent1
+ else self.derivedRefinedType(parent1, self.refinedName, self.refinedInfo)
+ case self: TypeProxy =>
+ self.underlying.widenToNamedTypeParams(params)
+ case self: AndOrType =>
+ self.derivedAndOrType(
+ self.tp1.widenToNamedTypeParams(params), self.tp2.widenToNamedTypeParams(params))
+ }
+ }
+
/** The Lambda trait underlying a type lambda */
def LambdaTrait(implicit ctx: Context): Symbol = self.stripTypeVar match {
case RefinedType(parent, tpnme.hkApply) =>