aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-01-20 11:46:30 +0100
committerMartin Odersky <odersky@gmail.com>2013-01-20 11:46:30 +0100
commitf0006cf691aab04faf79fa00ba578634a5497892 (patch)
tree926679ec917aa8a3076cced4954e3a0fa2221fd9 /src/dotty/tools/dotc
parent7ec55667d7d206cdf3de6d629cace47996a796bb (diff)
downloaddotty-f0006cf691aab04faf79fa00ba578634a5497892.tar.gz
dotty-f0006cf691aab04faf79fa00ba578634a5497892.tar.bz2
dotty-f0006cf691aab04faf79fa00ba578634a5497892.zip
Fleshed out Flags architecture and started work on Symbols.
Diffstat (limited to 'src/dotty/tools/dotc')
-rw-r--r--src/dotty/tools/dotc/core/Annotations.scala1
-rw-r--r--src/dotty/tools/dotc/core/Definitions.scala1
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala118
-rw-r--r--src/dotty/tools/dotc/core/Flags.scala280
-rw-r--r--src/dotty/tools/dotc/core/Referenceds.scala7
-rw-r--r--src/dotty/tools/dotc/core/SubTypers.scala41
-rw-r--r--src/dotty/tools/dotc/core/Symbols.scala46
-rw-r--r--src/dotty/tools/dotc/core/Types.scala53
8 files changed, 490 insertions, 57 deletions
diff --git a/src/dotty/tools/dotc/core/Annotations.scala b/src/dotty/tools/dotc/core/Annotations.scala
index 48165f488..756430fb3 100644
--- a/src/dotty/tools/dotc/core/Annotations.scala
+++ b/src/dotty/tools/dotc/core/Annotations.scala
@@ -2,6 +2,7 @@ package dotty.tools.dotc.core
object Annotations {
+ abstract class Annotation
abstract class AnnotationInfo
} \ No newline at end of file
diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala
index 8e76282a3..40f12a1b6 100644
--- a/src/dotty/tools/dotc/core/Definitions.scala
+++ b/src/dotty/tools/dotc/core/Definitions.scala
@@ -18,6 +18,7 @@ class Definitions(implicit ctx: Context) {
lazy val SingletonClass: ClassSymbol = ???
lazy val SingletonType = SingletonClass.typeConstructor
lazy val ArrayClass: ClassSymbol = ???
+ lazy val uncheckedStableClass: ClassSymbol = ???
def init() =
if (!isInitialized) {
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala
index bbbbaa74b..72a55944d 100644
--- a/src/dotty/tools/dotc/core/Denotations.scala
+++ b/src/dotty/tools/dotc/core/Denotations.scala
@@ -14,20 +14,23 @@ object Denotations {
*/
abstract class Denotation(initFlags: FlagSet) extends SymRefd {
- def symbol: Symbol
-
def owner: Symbol
def name: Name
+ def symbol: Symbol
+
private[this] var currentFlags: FlagSet = initFlags
def flags: FlagSet = currentFlags
def info: Type
- def setFlag(flag: FlagSet): Unit =
- currentFlags = initFlags
+ def setFlags(flags: FlagSet): Unit =
+ currentFlags |= flags
+
+ def resetFlags(flags: FlagSet): Unit =
+ currentFlags &~= flags
/** is this symbol a class? */
def isClass: Boolean = false
@@ -43,25 +46,50 @@ object Denotations {
override protected def copy(s: Symbol, i: Type): SymRefd = new UniqueSymRefd(s, i, validFor)
}
- class NonClassDenotation(
- override val symbol: Symbol,
- override val owner: Symbol,
- override val name: Name,
- val initFlags: FlagSet,
- override val info: Type
+ class CompleteDenotation(
+ val symbol: Symbol,
+ val owner: Symbol,
+ val name: Name,
+ initFlags: FlagSet,
+ val info: Type
) extends Denotation(initFlags)
- class ClassDenotation(
- override val symbol: ClassSymbol,
- override val owner: Symbol,
- override val name: Name,
- val initFlags: FlagSet,
- val parents: List[Type],
- val decls: Scope)(implicit ctx: Context) extends Denotation(initFlags) {
+ abstract class LazyDenotation(
+ val symbol: Symbol,
+ val owner: Symbol,
+ val name: Name,
+ initFlags: FlagSet
+ ) extends Denotation(initFlags) {
+
+ private var currentInfo: Type = null
+
+ override def flags = {
+ val fs = super.flags
+ if (fs is Unloaded) { load(); super.flags }
+ else fs
+ }
+
+ override def info = {
+ if (currentInfo == null) complete()
+ currentInfo
+ }
+
+ def load(): Unit
+ def complete(): Unit
+ }
+
+ abstract class ClassDenotation(initFlags: FlagSet)(implicit ctx: Context)
+ extends Denotation(initFlags) {
import NameFilter._
import util.LRU8Cache
- def typeParams: List[TypeSymbol] = ???
+ val symbol: ClassSymbol
+
+ def typeParams: List[TypeSymbol]
+
+ def parents: List[Type]
+
+ def decls: Scope
val info = ClassInfo(owner.thisType, this)
@@ -157,7 +185,7 @@ object Denotations {
parent.deref match {
case classd: ClassDenotation =>
includeFingerPrint(bits, classd.definedFingerPrint)
- parent.deref setFlag Frozen
+ parent.deref setFlags Frozen
case _ =>
}
ps = ps.tail
@@ -171,7 +199,7 @@ object Denotations {
* someone does a findMember on a subclass.
*/
def enter(sym: Symbol)(implicit ctx: Context) = {
- require(!(flags intersects Frozen))
+ require(!(this is Frozen))
decls enter sym
if (definedFingerPrintCache != null)
includeName(definedFingerPrintCache, sym.name)
@@ -184,7 +212,7 @@ object Denotations {
* someone does a findMember on a subclass.
*/
def delete(sym: Symbol)(implicit ctx: Context) = {
- require(!(flags intersects Frozen))
+ require(!(this is Frozen))
decls unlink sym
if (definedFingerPrintCache != null)
computeDefinedFingerPrint
@@ -284,6 +312,51 @@ object Denotations {
}
}
+ class CompleteClassDenotation(
+ val symbol: ClassSymbol,
+ val owner: Symbol,
+ val name: Name,
+ initFlags: FlagSet,
+ val typeParams: List[TypeSymbol],
+ val parents: List[Type],
+ val decls: Scope
+ )(implicit ctx: Context) extends ClassDenotation(initFlags)
+
+ abstract class LazyClassDenotation(
+ val symbol: ClassSymbol,
+ val owner: Symbol,
+ val name: Name,
+ initFlags: FlagSet
+ )(implicit ctx: Context) extends ClassDenotation(initFlags) {
+
+ protected var _typeParams: List[TypeSymbol] = null
+ protected var _parents: List[Type] = null
+ protected var _decls: Scope = null
+
+ override def flags = {
+ val fs = super.flags
+ if (fs is Unloaded) { load(); flags } else fs
+ }
+
+ def typeParams: List[TypeSymbol] = {
+ val tparams = _typeParams
+ if (tparams == null) { load(); typeParams } else tparams
+ }
+
+ def parents: List[Type] = {
+ val ps = _parents
+ if (ps == null) { complete(); parents } else ps
+ }
+
+ def decls: Scope = {
+ val ds = _decls
+ if (ds == null) { complete(); decls } else ds
+ }
+
+ def load(): Unit
+ def complete(): Unit
+ }
+
object NoDenotation extends Denotation(Flags.Empty) {
override def symbol: Symbol = NoSymbol
override def owner: Symbol = throw new AssertionError("NoDenotation.owner")
@@ -314,4 +387,7 @@ object Denotations {
def newNameFilter: FingerPrint = new Array[Long](DefinedNamesWords)
}
+
+ implicit def toFlagSet(denot: Denotation): FlagSet = denot.flags
+
} \ No newline at end of file
diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala
index f4a111632..1b1f2c618 100644
--- a/src/dotty/tools/dotc/core/Flags.scala
+++ b/src/dotty/tools/dotc/core/Flags.scala
@@ -12,7 +12,9 @@ object Flags {
*/
case class FlagSet(val bits: Long) extends AnyVal {
- def | (that: FlagSet) =
+ /** The union of this flag set and the given flag set
+ */
+ def | (that: FlagSet): FlagSet =
if (bits == 0) that
else if (that.bits == 0) this
else {
@@ -21,28 +23,55 @@ object Flags {
FlagSet(tbits | ((this.bits | that.bits) & ~TYPEFLAGS))
}
+ /** The union of this flag set and the given flag conjunction seen as
+ * a flag set.
+ */
+ def | (that: FlagConjunction): FlagSet = this | FlagSet(that.bits)
+
+ /** The intersection of this flag set and the given flag set */
def & (that: FlagSet) = FlagSet(bits & that.bits)
- def intersects(flags: FlagSet) = {
+ /** The intersection of this flag set with the complement of the given flag set */
+ def &~ (that: FlagSet) = {
+ val tbits = bits & that.bits & TYPEFLAGS
+ assert(tbits != 0, s"illegal flagset combination: $this and $that")
+ FlagSet(tbits | ((this.bits & ~that.bits) & ~TYPEFLAGS))
+ }
+
+ /** Does this flag set have a non-empty intersection with the given flag set?
+ * Pre: The intersection of the typeflags of both sets must be non-empty.
+ */
+ def is(flags: FlagSet) = {
val fs = bits & flags.bits
(fs & TYPEFLAGS) != 0 &&
fs > TYPEFLAGS
}
- def intersects(flags: FlagSet, butNot: FlagSet) = {
+ /** Does this flag set have a non-empty intersection with the given flag set,
+ * and at the same time contain none of the flags in the `butNot` set?
+ * Pre: The intersection of the typeflags of both sets must be non-empty.
+ */
+ def is(flags: FlagSet, butNot: FlagSet) = {
val fs = bits & flags.bits
(fs & TYPEFLAGS) != 0 &&
fs > TYPEFLAGS &&
(bits & butNot.bits) == 0
}
- def contains(flags: FlagSet) = {
+ /** Does this flag set have all of the flags in given flag conjunction?
+ * Pre: The intersection of the typeflags of both sets must be non-empty.
+ */
+ def is(flags: FlagConjunction) = {
val fs = bits & flags.bits
(fs & TYPEFLAGS) != 0 &&
(fs >> TYPESHIFT) == (flags.bits >> TYPESHIFT)
}
- def contains(flags: FlagSet, butNot: FlagSet) = {
+ /** Does this flag set have all of the flags in given flag conjunction?
+ * and at the same time contain none of the flags in the `butNot` set?
+ * Pre: The intersection of the typeflags of both sets must be non-empty.
+ */
+ def is(flags: FlagConjunction, butNot: FlagSet) = {
val fs = bits & (flags.bits | butNot.bits)
(fs & TYPEFLAGS) != 0 &&
(fs >> TYPESHIFT) == (flags.bits >> TYPESHIFT)
@@ -54,48 +83,253 @@ object Flags {
private def flagString(idx: Int): Set[String] =
kindIndices.map(flagName(idx)).filterNot(_.isEmpty)
+ /** The string representation of this flag set */
override def toString =
(2 to MaxFlag).flatMap(flagString).mkString(" ")
}
- final val TYPEFLAGS = 3L
- final val TYPESHIFT = 2
- final val TERMindex = 0
- final val TYPEindex = 1
- final val TERMS = 1 << TERMindex
- final val TYPES = 1 << TYPEindex
+ /** A class representing flag sets that should be tested
+ * conjunctively. I.e. for a flag conjunction `fc`,
+ * `x is fc` tests whether `x` contains all flags in `fc`.
+ */
+ case class FlagConjunction(bits: Long)
+
+ private final val TYPEFLAGS = 3L
+ private final val TYPESHIFT = 2
+ private final val TERMindex = 0
+ private final val TYPEindex = 1
+ private final val TERMS = 1 << TERMindex
+ private final val TYPES = 1 << TYPEindex
- final val MaxFlag = 63
+ private final val MaxFlag = 63
private var flagName = Array.fill(64, 2)("")
private val kindIndices = Set(TERMindex, TYPEindex)
- /** The flag with given index between 2 and 63 which applies to terms */
+ /** The flag with given index between 2 and 63 which applies to terms.
+ * Installs given name as the name of the flag. */
def termFlag(index: Int, name: String): FlagSet = {
flagName(index)(TERMindex) = name
- FlagSet(TERMS | (1L << index))
+ termFlag(index)
}
- /** The flag with given index between 2 and 63 which applies to types */
+ /** The flag with given index between 2 and 63 which applies to terms. */
+ def termFlag(index: Int) = FlagSet(TERMS | (1L << index))
+
+ /** The flag with given index between 2 and 63 which applies to types.
+ * Installs given name as the name of the flag. */
def typeFlag(index: Int, name: String): FlagSet = {
flagName(index)(TYPEindex) = name
- FlagSet(TYPES | (1L << index))
+ typeFlag(index)
}
+ /** The flag with given index between 2 and 63 which applies to terms. */
+ def typeFlag(index: Int) = FlagSet(TYPES | (1L << index))
+
/** The flag with given index between 2 and 63 which applies to both terms and types */
def commonFlag(index: Int, name: String): FlagSet =
- termFlag(index, name) | typeFlag(index, name)
+ termFlag(index, name) | typeFlag(index)
- // Available flags:
+ /** The conjunction of all flags in given flag set */
+ def allOf(flags: FlagSet) = FlagConjunction(flags.bits)
+ /** The empty flag set */
final val Empty = FlagSet(0)
- final val Private = commonFlag(3, "private")
- final val Accessor = termFlag(4, "<accessor>")
+ // Available flags:
+
+ /** Labeled with `private` modifier */
+ final val Private = commonFlag(2, "private")
+
+ /** Labeled with `protected` modifier */
+ final val Protected = commonFlag(3, "protected")
+
+ /** Labeled with `override` modifier */
+ final val Override = commonFlag(4, "override")
+
+ /** A declared, but not defined member */
+ final val Deferred = commonFlag(5, "<deferred>")
+
+ /** Labeled with `final` modifier */
+ final val Final = commonFlag(6, "final")
+
+ /** A method. !!! needed? */
+ final val Method = termFlag(7, "<method>")
+
+ /** An abstract class */
+ final val Abstract = typeFlag(8, "abstract")
+
+ /** A trait that has only abstract methods as members
+ * (and therefore can be represented by a Java interface
+ */
+ final val Interface = typeFlag(9, "interface")
+
+ /** A value or class implementing a module */
+ final val Module = commonFlag(10, "module")
+ final val ModuleObj = termFlag(10)
+ final val ModuleClass = typeFlag(10)
+
+ /** Labeled with `implicit` modifier */
+ final val Implicit = termFlag(11, "implicit")
+
+ /** Labeled with `sealed` modifier */
+ final val Sealed = typeFlag(12, "sealed")
+
+ /** A case class or its companion object */
+ final val Case = commonFlag(13, "case")
+ final val CaseClass = typeFlag(13)
+ final val CaseObj = termFlag(13)
+
+ /** A lazy val */
+ final val Lazy = termFlag(14, "lazy")
+
+ /** A mutable var */
+ final val Mutable = termFlag(14, "mutable")
+
+ /** A (term or type) parameter to a class or method */
+ final val Param = commonFlag(15, "<param>")
+ final val TermParam = termFlag(15)
+ final val TypeParam = typeFlag(15)
+
+ /** A value or class representing a package */
+ final val Package = commonFlag(16, "<package>")
+ final val PackageObj = termFlag(16)
+ final val PackageClass = typeFlag(16)
+
+ /** A by-name parameter !!! needed? */
+ final val ByNameParam = termFlag(17, "<by-name>")
+
+ /** A covariant type variable */
+ final val Covariant = typeFlag(17, "<covariant>")
+
+ /** Method is a label. */
+ final val Label = termFlag(18, "<label>")
+
+ /** Symbol is a macro */
+ final val Macro = commonFlag(???, "<macro>")
+
+ /** A contravariant type variable */
+ final val Contravariant = typeFlag(18, "<contravariant>")
+
+ /** combination of abstract & override */
+ final val AbsOverride = termFlag(19, "abstract override")
+
+ /** Symbol is local to current class (i.e. private[this] or protected[this]
+ * pre: Private or Protected are also set
+ */
+ final val Local = commonFlag(20, "<local>")
+
+ /** Symbol is defined by a Java class */
+ final val Java = commonFlag(21, "<java>")
+
+ /** A compiler-generated symbol. which is visible for type-checking
+ * (compare with artifact)
+ */
+ final val Synthetic = commonFlag(22, "<synthetic>")
+
+ /** Method is assumed to be stable */
+ final val Stable = termFlag(23, "<stable>")
+
+ final val Static = commonFlag(24, "<static>")
+
+ /** A value or variable accessor (getter or setter) */
+ final val Accessor = termFlag(25, "<accessor>")
+
+ /** A case parameter (or its accessor, or a GADT skolem) */
+ final val CaseAccessor = termFlag(26, "<caseaccessor>")
+
+ /** A super accessor */
+ final val SuperAccessor = termFlag(27, "<superaccessor>")
+
+ /** A field generated for a primary constructor parameter (no matter if it's a 'val' or not),
+ * or an accessor of such a field.
+ */
+ final val ParamAccessor = termFlag(28, "<paramaccessor>")
+
+ /** A parameter with a default value */
+ final val DefaultParam = termFlag(27, "<defaultparam>")
+
+ /** A trait */
+ final val Trait = typeFlag(27, "<trait>")
+
+ /** A bridge method. Set by Erasure */
+ final val Bridge = termFlag(28, "<bridge>")
+
+ /** Symbol is initialized to the default value, e.g. var x: T = _ */
+ final val DefaultInit = termFlag(29, "<defaultinit>")
+
+ /** An error symbol */
+ final val Erroneous = commonFlag(???, "<is-error>")
+
+ /** Denotation has not yet been loaded */
+ final val Unloaded = commonFlag(32, "??")
+
+ /** Denotation is in train of being loaded and completed, flag to catch cyclic dependencies */
+ final val Locked = commonFlag(???, "<locked>")
+
+ /** Variable is accessed from nested function. */
+ final val Captured = termFlag(???, "<captured>")
- final val Error = FlagSet(1 << 32)
- final val Frozen = FlagSet(???)
- final val Package = FlagSet(???)
+ /** Class symbol is defined in this/superclass constructor. */
+ final val Inconstructor = typeFlag(???, "<in-constructor>")
+ /** Class is not allowed to accept new members because fingerprint of subclass has been taken */
+ final val Frozen = typeFlag(???, "<frozen>")
+
+ /** Class has been lifted out to package level, local value has been lifted out to class level */
+ final val Lifted = termFlag(???, "<lifted>")
+
+ /** Term member has been mixed in */
+ final val MixedIn = termFlag(???, "<mixedin>")
+
+ /** Symbol is a generated specialized member */
+ final val Specialized = commonFlag(???, "<specialized>")
+
+ /** Symbol is a Java-style varargs method */
+ final val JavaVarargs = termFlag(???, "<varargs>")
+
+ /** Symbol is a Java varargs bridge */
+ final val VBridge = termFlag(???, "<vbridge>")
+
+ /** Symbol is a method which should be marked ACC_SYNCHRONIZED */
+ final val Synchronized = termFlag(???, "<synchronized>")
+
+ /** Symbol should be ignored when typechecking; will be marked ACC_SYNTHETIC in bytecode */
+ final val Artifact = commonFlag(???, "<artifact>")
+
+ /** Symbol is an implementation class */
+ final val ImplClass = typeFlag(???, "<implclass>")
+
+// --------- Combined Flag Sets and Conjunctions ----------------------
+
+ /** Flags representing source modifiers */
+ final val ModifierFlags =
+ Private | Protected | Abstract | Final | Sealed |
+ Override | Case | Implicit | AbsOverride | Lazy
+
+ /** Flags representing access rights */
+ final val AccessFlags = Private | Protected | Local
+
+ /** These flags are not pickled */
+ final val FlagsNotPickled =
+ Erroneous | Lifted | Unloaded | Frozen
+
+ /** These flags are pickled */
+ //final val PickledFlags = InitialFlags & ~FlagsNotPickled
+
+
+ /** A value that's unstable unless complemented with a Stable flag */
+ final val UnstableValue = Mutable | Method | ByNameParam
+
+ /** Labeled private[this] */
+ final val PrivateLocal = allOf(Private | Local)
+
+ /** Labeled `protected[this]` */
+ final val ProtectedLocal = allOf(Protected | Local)
+
+ /** Labeled `abstract` and `override`; only used in Parser,
+ * symbols are labeled AbsOverride instead
+ */
+ final val AbstractOverride = allOf(Abstract | Override)
} \ No newline at end of file
diff --git a/src/dotty/tools/dotc/core/Referenceds.scala b/src/dotty/tools/dotc/core/Referenceds.scala
index f0db3ff6c..7ec862be2 100644
--- a/src/dotty/tools/dotc/core/Referenceds.scala
+++ b/src/dotty/tools/dotc/core/Referenceds.scala
@@ -77,6 +77,12 @@ object Referenceds {
/** Is this a reference to a type symbol? */
def isType: Boolean = false
+ /** Is this a reference to a term symbol? */
+ def isTerm: Boolean = !isType
+
+ /** Is this reference overloaded? */
+ def isOverloaded = isInstanceOf[OverloadedRef]
+
/** The signature of the reference */
def signature: Signature
@@ -328,6 +334,7 @@ object Referenceds {
val info = NoType
validFor = Nowhere
override def exists = false
+ override def isTerm = false
}
// --------------- ReferencedSets -------------------------------------------------
diff --git a/src/dotty/tools/dotc/core/SubTypers.scala b/src/dotty/tools/dotc/core/SubTypers.scala
index 602b380f4..29c7b7388 100644
--- a/src/dotty/tools/dotc/core/SubTypers.scala
+++ b/src/dotty/tools/dotc/core/SubTypers.scala
@@ -203,6 +203,47 @@ object SubTypers {
true
}
+ /** A function implementing `tp1` matches `tp2`. */
+ final def matchesType(tp1: Type, tp2: Type, alwaysMatchSimple: Boolean): Boolean = tp1 match {
+ case tp1: MethodType =>
+ tp2 match {
+ case tp2: MethodType =>
+ tp1.isImplicit == tp2.isImplicit &&
+ matchingParams(tp1.paramTypes, tp2.paramTypes, tp1.isJava, tp2.isJava) &&
+ matchesType(tp1.resultType, tp2.resultType.subst(tp2, tp1), alwaysMatchSimple)
+ case tp2: ExprType =>
+ tp1.paramNames.isEmpty &&
+ matchesType(tp1.resultType, tp2.resultType, alwaysMatchSimple)
+ case _ =>
+ false
+ }
+ case tp1: ExprType =>
+ tp2 match {
+ case tp2: MethodType =>
+ tp2.paramNames.isEmpty &&
+ matchesType(tp1.resultType, tp2.resultType, alwaysMatchSimple)
+ case tp2: ExprType =>
+ matchesType(tp1.resultType, tp2.resultType, alwaysMatchSimple)
+ case _ =>
+ matchesType(tp1.resultType, tp2, alwaysMatchSimple)
+ }
+ case tp1: PolyType =>
+ tp2 match {
+ case tp2: PolyType =>
+ sameLength(tp1.paramNames, tp2.paramNames) &&
+ matchesType(tp1.resultType, tp2.resultType.subst(tp2, tp1), alwaysMatchSimple)
+ case _ =>
+ false
+ }
+ case _ =>
+ tp2 match {
+ case _: MethodType | _: PolyType =>
+ false
+ case _ =>
+ alwaysMatchSimple || isSameType(tp1, tp2)
+ }
+ }
+
/** Are `syms1` and `syms2` parameter lists with pairwise equivalent types? */
private def matchingParams(formals1: List[Type], formals2: List[Type], isJava1: Boolean, isJava2: Boolean): Boolean = formals1 match {
case Nil =>
diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala
index 331c168a8..bd3ab18f9 100644
--- a/src/dotty/tools/dotc/core/Symbols.scala
+++ b/src/dotty/tools/dotc/core/Symbols.scala
@@ -10,30 +10,46 @@ import Decorators._
import Symbols._
import Contexts._
import Denotations._
-import Types._
+import Types._, Annotations._
import Referenceds.{Referenced, SymRefd, OverloadedRef}
import collection.mutable
object Symbols {
- /**
- * A SymRef is a period-dependent reference to a denotation.
- * Given a period, its `deref` method resolves to a Symbol.
+ /** A Symbol represents a Scala definition/declaration or a package.
*/
abstract class Symbol {
- def overriddenSymbol(inclass: ClassSymbol)(implicit ctx: Context): Symbol =
- if (owner isSubClass inclass) ???
+ /** The non-private symbol whose type matches the type of this symbol
+ * in in given class.
+ *
+ * @param ofClass The class containing the symbol's definition
+ * @param site The base type from which member types are computed
+ */
+ final def matchingSymbol(inClass: Symbol, site: Type)(implicit ctx: Context): Symbol = {
+ var ref = inClass.info.nonPrivateDecl(name)
+ if (ref.isTerm) {
+ val targetType = site.memberInfo(this)
+ if (ref.isOverloaded) ref = ref.atSignature(targetType.signature)
+ val candidate = ref.symbol
+ if (site.memberInfo(candidate) matches targetType) candidate
+ else NoSymbol
+ } else ref.symbol
+ }
+
+ def overriddenSymbol(inClass: ClassSymbol)(implicit ctx: Context): Symbol =
+ if (owner isSubClass inClass) matchingSymbol(inClass, owner.thisType)
else NoSymbol
def isProtected: Boolean = ???
- def isStable: Boolean = ???
+ def isStable(implicit ctx: Context): Boolean = false
def accessBoundary: ClassSymbol = ???
def isContainedIn(boundary: ClassSymbol) = ???
def baseClasses: List[ClassSymbol] = ???
def exists = true
-
+ def hasAnnotation(ann: Annotation): Boolean = ???
+ def hasAnnotation(ann: ClassSymbol): Boolean = ???
def orElse(that: => Symbol) = if (exists) this else that
@@ -50,11 +66,10 @@ object Symbols {
(this isAsAccessible that)
def isAsAccessible(that: Symbol)(implicit ctx: Context): Boolean =
- !this.isProtected && !that.isProtected && // protected members are incomparable
+ !(this is Protected) && !(that is Protected) && // protected members are incomparable
(that.accessBoundary isContainedIn this.accessBoundary) &&
this.isStable || !that.isStable
-
/** Set the denotation of this symbol.
*/
def setDenotation(denot: Denotation) =
@@ -161,8 +176,15 @@ object Symbols {
abstract class TermSymbol extends Symbol {
def name: TermName
def isType = true
+
+ override def isStable(implicit ctx: Context) = !(
+ this.is(UnstableValue, butNot = Stable) ||
+ info.isVolatile && !hasAnnotation(defn.uncheckedStableClass)
+ )
}
+ final val MutableMethodByNameParam = Mutable | Method | ByNameParam
+
trait RefinementSymbol extends Symbol {
override def deref(implicit ctx: Context) = lastDenot
}
@@ -220,7 +242,11 @@ object Symbols {
def loadDenot(implicit ctx: Context): Denotation = NoDenotation
override def exists = false
def isType = false
+ override def isTerm = false
}
implicit def defn(implicit ctx: Context): Definitions = ctx.root.definitions
+
+ implicit def toFlagSet(sym: Symbol)(implicit ctx: Context): FlagSet = sym.flags
+
} \ No newline at end of file
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index be627faf4..d48526fdb 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -157,7 +157,8 @@ object Types {
final def isNotNull: Boolean = false
/** Is this type produced as a repair for an error? */
- final def isError(implicit ctx: Context): Boolean = (typeSymbol hasFlag Error) || (termSymbol hasFlag Error)
+ final def isError(implicit ctx: Context): Boolean =
+ (typeSymbol is Erroneous) || (termSymbol is Erroneous)
/** Is some part of this type produced as a repair for an error? */
final def isErroneous(implicit ctx: Context): Boolean = exists(_.isError)
@@ -256,7 +257,26 @@ object Types {
/** The declaration of this type with given name */
final def decl(name: Name)(implicit ctx: Context): Referenced =
- decls.refsNamed(name).toRef
+ findDecl(name, this, Flags.Empty)
+
+ /** The non-private declaration of this type with given name */
+ final def nonPrivateDecl(name: Name)(implicit ctx: Context): Referenced =
+ findDecl(name, this, Flags.Private)
+
+ /** The non-private declaration of this type with given name */
+ final def findDecl(name: Name, pre: Type, excluded: FlagSet)(implicit ctx: Context): Referenced = this match {
+ case tp: RefinedType =>
+ tp.findDecl(name, pre)
+ case tp: ClassInfo =>
+ tp.classd.decls
+ .refsNamed(name)
+ .filterAccessibleFrom(pre)
+ .filterExcluded(excluded)
+ .asSeenFrom(pre, tp.classd.symbol)
+ .toRef
+ case tp: TypeProxy =>
+ tp.underlying.findDecl(name, pre, excluded)
+ }
/** The member of this type with given name */
final def member(name: Name)(implicit ctx: Context): Referenced =
@@ -302,6 +322,30 @@ object Types {
final def =:=(that: Type)(implicit ctx: Context): Boolean =
ctx.subTyper.isSameType(this, that)
+ /** Is this type close enough to that type so that members
+ * with the two type would override each other?
+ * This means:
+ * - Either both types are polytypes with the same number of
+ * type parameters and their result types match after renaming
+ * corresponding type parameters
+ * - Or both types are (possibly nullary) method types with equivalent type parameter types
+ * and matching result types
+ * - Or both types are equivalent
+ * - Or phase.erasedTypes is false and both types are neither method nor
+ * poly types.
+ */
+ def matches(that: Type)(implicit ctx: Context): Boolean =
+ ctx.subTyper.matchesType(this, that, !ctx.phase.erasedTypes)
+
+ /** Does this type match that type
+ *
+ */
+
+ /** The info of `sym`, seen as a member of this type. */
+ final def memberInfo(sym: Symbol)(implicit ctx: Context): Type = {
+ sym.info.asSeenFrom(this, sym.owner)
+ }
+
/** Widen from singleton type to its underlying non-singleton
* base type by applying one or more `underlying` dereferences,
* identity for all other types. Example:
@@ -338,7 +382,9 @@ object Types {
}
final def asSeenFrom(pre: Type, clazz: Symbol)(implicit ctx: Context): Type =
- if (clazz.isStaticMono || ctx.erasedTypes && clazz != defn.ArrayClass) this
+ if (clazz.isStaticMono ||
+ ctx.erasedTypes && clazz != defn.ArrayClass ||
+ (pre eq clazz.thisType)) this
else ctx.asSeenFrom(this, pre, clazz, null)
/** The signature of this type. This is by default NullSignature,
@@ -803,6 +849,7 @@ object Types {
abstract case class ExprType(resultType: Type) extends CachedProxyType {
override def underlying(implicit ctx: Context): Type = resultType
+ override def signature: Signature = Nil
def derivedExprType(rt: Type)(implicit ctx: Context) =
if (rt eq resultType) this else ExprType(rt)
override def computeHash = doHash(resultType)