aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-02-21 14:08:39 +0100
committerMartin Odersky <odersky@gmail.com>2013-02-21 14:08:39 +0100
commit58b7b61fb8ffda09dbec4427476a47b4e3a505bc (patch)
tree10179fe6510d9d059cd8767f05ea0e4fe7f60e70 /src/dotty/tools/dotc/core
parent3c2d0d752dcb690bd37622cf8593bc359d6b35aa (diff)
downloaddotty-58b7b61fb8ffda09dbec4427476a47b4e3a505bc.tar.gz
dotty-58b7b61fb8ffda09dbec4427476a47b4e3a505bc.tar.bz2
dotty-58b7b61fb8ffda09dbec4427476a47b4e3a505bc.zip
More utility methods and split up filter
More utility methods in types. Also replaced Denotation#filter with a set of more useful operations.
Diffstat (limited to 'src/dotty/tools/dotc/core')
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala49
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala17
-rw-r--r--src/dotty/tools/dotc/core/TypeOps.scala2
-rw-r--r--src/dotty/tools/dotc/core/Types.scala51
4 files changed, 91 insertions, 28 deletions
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala
index 924057935..c7c257f5c 100644
--- a/src/dotty/tools/dotc/core/Denotations.scala
+++ b/src/dotty/tools/dotc/core/Denotations.scala
@@ -157,18 +157,31 @@ object Denotations {
def orElse(that: => Denotation) = if (this.exists) this else that
- /** The part of this denotation that satisfies the predicate, or NoDenotation is none exists */
- def filter(p: Symbol => Boolean)(implicit ctx: Context): Denotation
+ /** The set of alternative single-denotations making up this denotation */
+ def alts(p: Symbol => Boolean)(implicit ctx: Context): List[SingleDenotation] =
+ altsWith(scala.Function.const(true))
+
+ /** The alternatives of this denotation that satisfy the predicate `p`. */
+ def altsWith(p: Symbol => Boolean)(implicit ctx: Context): List[SingleDenotation]
+
+ /** The unique alternative of this denotation that satisfies the predicate `p`,
+ * or NoDenotation if no satisfying alternative exists.
+ * @throws TypeError if there is at more than one alternative that satisfies `p`.
+ */
+ def suchThat(p: Symbol => Boolean)(implicit ctx: Context): SingleDenotation
+
+ /** Does this denotation have an alternative that satisfies the predicate `p`? */
+ def hasAltWith(p: Symbol => Boolean)(implicit ctx: Context): Boolean
/** If this denotation is overloaded, filter with given predicate.
- * If result is still overloaded throw a TypeError
+ * If result is still overloaded throw a TypeError.
+ * Note: disambiguate is slightly different from suchThat in that
+ * single-denotations that do not satisfy the predicate are left alone
+ * (whereas suchThat would map them to NoDenotation).
*/
def disambiguate(p: Symbol => Boolean)(implicit ctx: Context): SingleDenotation = this match {
case sdenot: SingleDenotation => sdenot
- case mdenot => this filter p match {
- case sdenot: SingleDenotation => sdenot
- case mdenot => throw new TypeError(s"failure to disambiguate overloaded reference $mdenot")
- }
+ case mdenot => suchThat(p)
}
/** Return symbol in this denotation that satisfies the given predicate.
@@ -279,8 +292,18 @@ object Denotations {
def info = unsupported("info")
def signature = unsupported("signature")
def firstSym(implicit ctx: Context): Symbol = denot1.firstSym orElse denot2.firstSym
- def filter(p: Symbol => Boolean)(implicit ctx: Context): Denotation =
- (denot1 filter p) & (denot2 filter p)
+ def altsWith(p: Symbol => Boolean)(implicit ctx: Context): List[SingleDenotation] =
+ denot1.altsWith(p) ++ denot2.altsWith(p)
+ def suchThat(p: Symbol => Boolean)(implicit ctx: Context): SingleDenotation = {
+ val sd1 = denot1.suchThat(p)
+ val sd2 = denot2.suchThat(p)
+ if (sd1.exists)
+ if (sd2.exists) throw new TypeError(s"failure to disambiguate overloaded reference $this")
+ else sd1
+ else sd2
+ }
+ def hasAltWith(p: Symbol => Boolean)(implicit ctx: Context): Boolean =
+ denot1.hasAltWith(p) || denot2.hasAltWith(p)
def atSignature(sig: Signature): SingleDenotation =
denot1.atSignature(sig) orElse denot2.atSignature(sig)
def validFor = denot1.validFor & denot2.validFor
@@ -311,9 +334,15 @@ object Denotations {
def orElse(that: => SingleDenotation) = if (this.exists) this else that
- def filter(p: Symbol => Boolean)(implicit ctx: Context): SingleDenotation =
+ def altsWith(p: Symbol => Boolean)(implicit ctx: Context): List[SingleDenotation] =
+ if (p(symbol)) this :: Nil else Nil
+
+ def suchThat(p: Symbol => Boolean)(implicit ctx: Context): SingleDenotation =
if (p(symbol)) this else NoDenotation
+ def hasAltWith(p: Symbol => Boolean)(implicit ctx: Context): Boolean =
+ p(symbol)
+
def atSignature(sig: Signature): SingleDenotation =
if (sig == signature) this else NoDenotation
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index 73d14141c..2bafb7732 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -198,12 +198,13 @@ object SymDenotations {
|| (this.sourceFile.canonicalPath == that.sourceFile.canonicalPath)
)
- /** Is this a denotation of a stable term? */
- final def isStable(implicit ctx: Context) = !(
- isTerm &&
- this.is(UnstableValue, butNot = Stable) ||
- info.isVolatile && !hasAnnotation(defn.uncheckedStableClass)
- )
+ /** Is this a denotation of a stable term (or an arbitrary type)? */
+ final def isStable(implicit ctx: Context) = {
+ val isUnstable =
+ this.is(UnstableValue, butNot = Stable) ||
+ info.isVolatile && !hasAnnotation(defn.uncheckedStableClass)
+ !(isTerm && isUnstable)
+ }
/** Is this a subclass of the given class `base`? */
def isSubClass(base: Symbol)(implicit ctx: Context) = false
@@ -382,7 +383,7 @@ object SymDenotations {
*/
def companionModule(implicit ctx: Context): Symbol = {
owner.info.decl(name.toTermName)
- .filter(sym => sym.isModule && sym.isCoDefinedWith(symbol))
+ .suchThat(sym => sym.isModule && sym.isCoDefinedWith(symbol))
.symbol
}
@@ -392,7 +393,7 @@ object SymDenotations {
*/
def companionClass(implicit ctx: Context): Symbol =
owner.info.decl(name.toTypeName)
- .filter(sym => sym.isClass && sym.isCoDefinedWith(symbol))
+ .suchThat(sym => sym.isClass && sym.isCoDefinedWith(symbol))
.symbol
/** If this is a class, the module class of its companion object.
diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala
index f3193a95f..77038816e 100644
--- a/src/dotty/tools/dotc/core/TypeOps.scala
+++ b/src/dotty/tools/dotc/core/TypeOps.scala
@@ -73,7 +73,7 @@ trait TypeOps { this: Context =>
case tp: RefinedType =>
tp.parent.isVolatile ||
isAbstractIntersection(tp.parent) &&
- (tp.abstractMemberNames(tp) contains tp.name)
+ (tp.abstractMemberNames contains tp.name)
case tp: TypeProxy =>
tp.underlying.isVolatile
case AndType(l, r) =>
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 9b7a26dfe..60facee3c 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -93,18 +93,30 @@ object Types {
*/
final def abstractTypeNames(pre: Type)(implicit ctx: Context): Set[Name] =
memberNames(pre, abstractTypeNameFilter)
+ final def abstractTypeNames(implicit ctx: Context): Set[Name] =
+ abstractTypeNames(this)
/** The set of names that denote an abstract term member of this type
* which is also an abstract term member of `pre`
*/
final def abstractTermNames(pre: Type)(implicit ctx: Context): Set[Name] =
memberNames(pre, abstractTermNameFilter)
+ final def abstractTermNames(implicit ctx: Context): Set[Name] =
+ abstractTermNames(this)
/** The set of names that denote an abstract member of this type
* which is also an abstract member of `pre`
*/
final def abstractMemberNames(pre: Type)(implicit ctx: Context): Set[Name] =
abstractTypeNames(pre) | abstractTermNames(pre)
+ final def abstractMemberNames(implicit ctx: Context): Set[Name] =
+ abstractMemberNames(this)
+
+ final def abstractTermMembers(pre: Type)(implicit ctx: Context): Set[SingleDenotation] =
+ abstractTermNames.flatMap(name =>
+ pre.member(name).altsWith(_ is Deferred))
+ final def abstractTermMembers(implicit ctx: Context): Set[SingleDenotation] =
+ abstractTermMembers(this)
/** The set of names of members of this type that pass the given name filter
* when seen as members of `pre`. More precisely, these are all
@@ -127,6 +139,19 @@ object Types {
Set()
}
+ /** Is this type a value type */
+ final def isValueType: Boolean = this match {
+ case NoPrefix
+ | NoType
+ | WildcardType
+ | _: TypeBounds
+ | _: MethodType
+ | _: PolyType
+ | _: ExprType
+ | _: ClassInfo => false
+ case _ => true
+ }
+
/** Is this type a TypeBounds instance, with lower and upper bounds
* that are not identical?
*/
@@ -240,12 +265,20 @@ object Types {
}
/** The parameter types of a PolyType or MethodType, Empty list for others */
- def paramTypess(implicit ctx: Context): List[List[Type]] = this match {
+ def paramTypess: List[List[Type]] = this match {
case mt: MethodType => mt.paramTypes :: mt.resultType.paramTypess
case pt: PolyType => pt.paramTypess
case _ => Nil
}
+ /** The resultType of a PolyType, MethodType, or ExprType, the type itself for others */
+ def resultType: Type = this match {
+ case et: ExprType => et.resultType
+ case mt: MethodType => mt.resultType
+ case pt: PolyType => pt.resultType
+ case _ => this
+ }
+
/** Map function over elements of an AndType, rebuilding with & */
def mapAnd(f: Type => Type)(implicit ctx: Context): Type = this match {
case AndType(tp1, tp2) => tp1.mapAnd(f) & tp2.mapAnd(f)
@@ -387,14 +420,16 @@ object Types {
/** Widen from singleton type to its underlying non-singleton
* base type by applying one or more `underlying` dereferences,
- * identity for all other types. Example:
+ * Also go from => T to T.
+ * Identity for all other types. Example:
*
* class Outer { class C ; val x: C }
- * val o: Outer
+ * def o: Outer
* <o.x.type>.widen = o.C
*/
final def widen(implicit ctx: Context): Type = this match {
case tp: SingletonType => tp.underlying.widen
+ case tp: ExprType => tp.underlying.widen
case _ => this
}
@@ -406,8 +441,6 @@ object Types {
case _ => this
}
- //def resultType: Type = ???
-
/** The base classes of this type as determined by ClassDenotation
* in linearization order, with the class itself as first element.
* Inherited by all type proxies. `Nil` for all other types.
@@ -883,7 +916,7 @@ object Types {
// and therefore two different poly types would never be equal.
abstract case class MethodType(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type) extends CachedGroundType with BindingType {
- lazy val resultType = resultTypeExp(this)
+ override lazy val resultType = resultTypeExp(this)
def isJava = false
def isImplicit = false
@@ -954,7 +987,7 @@ object Types {
unique(new ImplicitMethodType(paramNames, paramTypes)(resultTypeExp))
}
- abstract case class ExprType(resultType: Type) extends CachedProxyType {
+ abstract case class ExprType(override val resultType: Type) extends CachedProxyType {
override def underlying(implicit ctx: Context): Type = resultType
override def signature: Signature = Nil
def derivedExprType(rt: Type)(implicit ctx: Context) =
@@ -972,7 +1005,7 @@ object Types {
case class PolyType(paramNames: List[TypeName])(paramBoundsExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type)
extends UncachedGroundType with BindingType {
lazy val paramBounds = paramBoundsExp(this)
- lazy val resultType = resultTypeExp(this)
+ override lazy val resultType = resultTypeExp(this)
override def signature = resultType.signature
@@ -1272,7 +1305,7 @@ object Types {
/** A filter for names of deferred term definitions of a given type */
object abstractTermNameFilter extends NameFilter {
def apply(pre: Type, name: Name)(implicit ctx: Context): Boolean =
- name.isTermName && ((pre member name).symbol is Deferred)
+ name.isTermName && (pre member name).hasAltWith(_ is Deferred)
}
// ----- Exceptions -------------------------------------------------------------