diff options
author | Martin Odersky <odersky@gmail.com> | 2016-03-25 10:34:54 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2016-03-30 09:51:03 +0200 |
commit | d0f9848486be2c8cec61acb94a592e8c9d4f842f (patch) | |
tree | 788bbed18e395c71eb2374c543b2cd6c2eff866d /src/dotty/tools/dotc/core/TypeApplications.scala | |
parent | 0474de635bee32f6d78726072230c9d572de0d52 (diff) | |
download | dotty-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.scala | 60 |
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) => |