aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-02-24 18:42:17 +0100
committerMartin Odersky <odersky@gmail.com>2013-02-24 18:42:17 +0100
commit36b9128d2214a927d642e87da3322b4ed4e76c58 (patch)
tree8a9c85a5b7568bb5b1eb4113d0ab122ae1af1bc1
parent7cde8b6d78022aadb00d3f82fb9019da39a62b49 (diff)
downloaddotty-36b9128d2214a927d642e87da3322b4ed4e76c58.tar.gz
dotty-36b9128d2214a927d642e87da3322b4ed4e76c58.tar.bz2
dotty-36b9128d2214a927d642e87da3322b4ed4e76c58.zip
Refactoring and cleanup of several symbol creation related aspects.
1. Went back to old completer model where completers are types. 2. Made class denotations a simple optimzation of symbol denotatons (with more caches) by moving all class-specific attributes into ClassInfo. 3. Now all symbol and symbol denotation creations are routed through one of 3 methods: newNakedSymbol, newNakedClassSymbol, newSymDenotation.
-rw-r--r--src/dotty/tools/dotc/config/JavaPlatform.scala4
-rw-r--r--src/dotty/tools/dotc/config/Platform.scala5
-rw-r--r--src/dotty/tools/dotc/core/Contexts.scala5
-rw-r--r--src/dotty/tools/dotc/core/Definitions.scala22
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala2
-rw-r--r--src/dotty/tools/dotc/core/Flags.scala5
-rw-r--r--src/dotty/tools/dotc/core/Printers.scala12
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala508
-rw-r--r--src/dotty/tools/dotc/core/SymbolLoaders.scala57
-rw-r--r--src/dotty/tools/dotc/core/Symbols.scala317
-rw-r--r--src/dotty/tools/dotc/core/TypeOps.scala2
-rw-r--r--src/dotty/tools/dotc/core/TypedTrees.scala11
-rw-r--r--src/dotty/tools/dotc/core/Types.scala60
-rw-r--r--src/dotty/tools/dotc/core/pickling/ClassfileParser.scala98
-rw-r--r--src/dotty/tools/dotc/core/pickling/UnPickler.scala40
15 files changed, 582 insertions, 566 deletions
diff --git a/src/dotty/tools/dotc/config/JavaPlatform.scala b/src/dotty/tools/dotc/config/JavaPlatform.scala
index 0c91ae2e7..bcb1939a8 100644
--- a/src/dotty/tools/dotc/config/JavaPlatform.scala
+++ b/src/dotty/tools/dotc/config/JavaPlatform.scala
@@ -7,7 +7,7 @@ import ClassPath.{ JavaContext, DefaultJavaContext }
import core.Contexts._
import core.SymDenotations._, core.Symbols._, core.SymbolLoader
-class JavaPlatform(base: ContextBase) extends Platform(base) {
+class JavaPlatform extends Platform {
private var currentClassPath: Option[MergedClassPath] = None
@@ -21,7 +21,7 @@ class JavaPlatform(base: ContextBase) extends Platform(base) {
def updateClassPath(subst: Map[ClassPath, ClassPath]) =
currentClassPath = Some(new DeltaClassPath(currentClassPath.get, subst))
- def rootLoader: ClassCompleter = ??? // = new loaders.PackageLoader(classPath)
+ def rootLoader(implicit ctx: Context): SymbolLoader = new ctx.base.loaders.PackageLoader(classPath)(ctx.condensed)
/** We could get away with excluding BoxedBooleanClass for the
* purpose of equality testing since it need not compare equal
diff --git a/src/dotty/tools/dotc/config/Platform.scala b/src/dotty/tools/dotc/config/Platform.scala
index 0385d80c5..19bdf00b1 100644
--- a/src/dotty/tools/dotc/config/Platform.scala
+++ b/src/dotty/tools/dotc/config/Platform.scala
@@ -9,15 +9,14 @@ package config
import io.{ClassPath, AbstractFile}
import core.Contexts._, core.Symbols._
-import core.SymDenotations.ClassCompleter
import core.SymbolLoader
/** The platform dependent pieces of Global.
*/
-abstract class Platform(base: ContextBase) {
+abstract class Platform {
/** The root symbol loader. */
- def rootLoader: ClassCompleter
+ def rootLoader(implicit ctx: Context): SymbolLoader
/** The compiler classpath. */
def classPath(implicit ctx: Context): ClassPath
diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala
index 9ca111dc0..388ae60ce 100644
--- a/src/dotty/tools/dotc/core/Contexts.scala
+++ b/src/dotty/tools/dotc/core/Contexts.scala
@@ -40,6 +40,7 @@ object Contexts {
with TypeOps
with Printers
with Symbols
+ with SymDenotations
with Cloneable {
implicit val ctx: Context = this
@@ -158,9 +159,9 @@ object Contexts {
val loaders = new SymbolLoaders
- val platform: Platform = new JavaPlatform(this)
+ val platform: Platform = new JavaPlatform
- val rootLoader: ClassCompleter = platform.rootLoader
+ def rootLoader(implicit ctx: Context): SymbolLoader = platform.rootLoader
val definitions = new Definitions()(initialCtx)
diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala
index ef9f3d70d..8b512be8a 100644
--- a/src/dotty/tools/dotc/core/Definitions.scala
+++ b/src/dotty/tools/dotc/core/Definitions.scala
@@ -30,8 +30,8 @@ class Definitions(implicit ctx: Context) {
scope.enter(tparam)
}
- private def specialPolyClass(name: TypeName, flags: FlagSet, parentConstrs: Type*): ClassSymbol = {
- def classDenot(cls: ClassSymbol) = {
+ private def specialPolyClass(name: TypeName, flags: FlagSet, parentConstrs: Type*): ClassSymbol =
+ ctx.newClassSymbolDenoting { cls =>
val paramDecls = newScope
val typeParam = newSyntheticTypeParam(cls, paramDecls)
def instantiate(tpe: Type) =
@@ -39,10 +39,10 @@ class Definitions(implicit ctx: Context) {
else tpe
val parents = parentConstrs.toList map instantiate
val parentRefs: List[TypeRef] = ctx.normalizeToRefs(parents, cls, paramDecls)
- CompleteClassDenotation(cls, ScalaPackageClass, name, flags, parentRefs, decls = paramDecls)(ctx)
+ ctx.SymDenotation(
+ cls, ScalaPackageClass, name, flags,
+ ClassInfo(ScalaPackageClass.thisType, cls, parentRefs, paramDecls))
}
- new ClassSymbol(NoCoord, classDenot, null)
- }
private def mkArityArray(name: String, arity: Int, countFrom: Int): Array[ClassSymbol] = {
val arr = new Array[ClassSymbol](arity)
@@ -50,12 +50,12 @@ class Definitions(implicit ctx: Context) {
arr
}
- lazy val RootClass: ClassSymbol = ctx.newLazyPackageSymbols(
- NoSymbol, nme.ROOT, ctx.rootLoader)._2
+ lazy val RootClass: ClassSymbol = ctx.newPackageSymbol(
+ NoSymbol, nme.ROOT, ctx.rootLoader).moduleClass.asClass
lazy val RootPackage: TermSymbol = ctx.newSymbol(
NoSymbol, nme.ROOTPKG, PackageCreationFlags, TypeRef(NoPrefix, RootClass))
- lazy val EmptyPackageClass = ctx.newPackageSymbols(RootClass, nme.EMPTY_PACKAGE)._2
+ lazy val EmptyPackageClass = ctx.newCompletePackageSymbol(RootClass, nme.EMPTY_PACKAGE).moduleClass.asClass
lazy val EmptyPackageVal = EmptyPackageClass.sourceModule
lazy val ScalaPackageVal = requiredPackage("scala")
@@ -66,15 +66,15 @@ class Definitions(implicit ctx: Context) {
lazy val ObjectClass = requiredClass("java.lang.Object")
lazy val AnyRefAlias: TypeSymbol = ctx.newSymbol(
ScalaPackageClass, tpnme.AnyRef, EmptyFlags, TypeAlias(ObjectClass.typeConstructor)).entered
- lazy val AnyClass: ClassSymbol = ctx.newClassSymbol(
+ lazy val AnyClass: ClassSymbol = ctx.newCompleteClassSymbol(
ScalaPackageClass, tpnme.Any, Abstract, Nil).entered
lazy val AnyValClass: ClassSymbol = requiredClass("scala.AnyVal")
lazy val NotNullClass = requiredClass("scala.NotNull")
- lazy val NothingClass: ClassSymbol = ctx.newClassSymbol(
+ lazy val NothingClass: ClassSymbol = ctx.newCompleteClassSymbol(
ScalaPackageClass, tpnme.Nothing, UninstantiatableFlags, List(AnyClass.typeConstructor)).entered
- lazy val NullClass: ClassSymbol = ctx.newClassSymbol(
+ lazy val NullClass: ClassSymbol = ctx.newCompleteClassSymbol(
ScalaPackageClass, tpnme.Null, UninstantiatableFlags, List(AnyRefAlias.typeConstructor)).entered
lazy val PredefModule = requiredModule("scala.Predef")
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala
index c7c257f5c..84564e7c7 100644
--- a/src/dotty/tools/dotc/core/Denotations.scala
+++ b/src/dotty/tools/dotc/core/Denotations.scala
@@ -525,7 +525,7 @@ object Denotations {
def missingHook(owner: Symbol, name: Name)(implicit ctx: Context): Symbol =
if (owner.isPackage && name.isTermName)
- ctx.newPackageSymbols(owner, name.asTermName)._1.entered
+ ctx.newCompletePackageSymbol(owner, name.asTermName).entered
else
NoSymbol
}
diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala
index 60f6025fd..bded3e822 100644
--- a/src/dotty/tools/dotc/core/Flags.scala
+++ b/src/dotty/tools/dotc/core/Flags.scala
@@ -271,7 +271,7 @@ object Flags {
final val Erroneous = commonFlag(???, "<is-error>")
/** Denotation is in train of being loaded and completed, flag to catch cyclic dependencies */
- final val Locked = commonFlag(???, "<locked>")
+ final val CompletionStarted = commonFlag(???, "<locked>")
/** Variable is accessed from nested function. */
final val Captured = termFlag(???, "<captured>")
@@ -326,6 +326,7 @@ object Flags {
final val SyntheticArtifact = Synthetic | Artifact
final val RetainedModuleFlags: FlagSet = ???
+ final val RetainedModuleClassFlags: FlagSet = ???
final val UninstantiatableFlags = Abstract | Final
@@ -333,7 +334,7 @@ object Flags {
final val InitialFlags: FlagSet = ???
/** These flags are not pickled */
- final val FlagsNotPickled = commonFlags(Erroneous, Lifted, Frozen)
+ final val FlagsNotPickled = commonFlags(Erroneous, Lifted, Frozen, CompletionStarted)
/** These flags are pickled */
final val PickledFlags = InitialFlags &~ FlagsNotPickled
diff --git a/src/dotty/tools/dotc/core/Printers.scala b/src/dotty/tools/dotc/core/Printers.scala
index 640e72d68..3a9aaeb5b 100644
--- a/src/dotty/tools/dotc/core/Printers.scala
+++ b/src/dotty/tools/dotc/core/Printers.scala
@@ -274,15 +274,15 @@ object Printers {
else
(if (lo.typeSymbol == defn.NothingClass) "" else ">: " + lo) +
(if (hi.typeSymbol == defn.AnyClass) "" else "<: " + hi)
- case ClassInfo(pre, cdenot) =>
+ case ClassInfo(pre, cdenot, cparents, decls, optSelfType) =>
val preStr = showLocal(pre)
val selfStr =
- if (cdenot.selfType == cdenot.typeConstructor) ""
- else s"this: ${show(cdenot.selfType, LeftArrowPrec)} =>"
- val parentsStr = cdenot.parents.map(show(_, WithPrec)).mkString(" with ")
+ if (optSelfType.exists) s"this: ${show(optSelfType, LeftArrowPrec)} =>"
+ else ""
+ val parentsStr = cparents.map(show(_, WithPrec)).mkString(" with ")
val declsStr =
- if (cdenot.decls.isEmpty) ""
- else "\n " + show(cdenot.decls.toList, "\n ")
+ if (decls.isEmpty) ""
+ else "\n " + show(decls.toList, "\n ")
s"""$parentsStr { $selfStr$declsStr
|} at $preStr""".stripMargin
case _ => ": " + showGlobal(tp)
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index c976bbf0d..ab52a188f 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -11,68 +11,100 @@ import scala.reflect.io.AbstractFile
import Decorators.SymbolIteratorDecorator
import annotation.tailrec
+trait SymDenotations {
+ import SymDenotations._
+
+ /** Factory method for SymDenotion creation. All creations
+ * should be done via this method.
+ */
+ def SymDenotation(
+ symbol: Symbol,
+ owner: Symbol,
+ name: Name,
+ initFlags: FlagSet,
+ initInfo: Type,
+ initPrivateWithin: Symbol = NoSymbol)(implicit ctx: Context): SymDenotation =
+ if (symbol.isClass) new ClassDenotation(symbol, owner, name, initFlags, initInfo, initPrivateWithin)
+ else new SymDenotation(symbol, owner, name, initFlags, initInfo, initPrivateWithin)
+
+}
object SymDenotations {
/** A denotation represents the contents of a definition
* during a period.
*/
- abstract class SymDenotation(initFlags: FlagSet) extends SingleDenotation {
-
-// ----- denotation fields and accessors ------------------------------
-
- /** The denoting symbol */
- def symbol: Symbol
-
- /** The owner. Owners form chains that always end in
- * defn.RootClass
- */
- def owner: Symbol
-
- /** The name */
- def name: Name
+ class SymDenotation private[SymDenotations] (
+ val symbol: Symbol,
+ _owner: Symbol,
+ val name: Name,
+ initFlags: FlagSet,
+ initInfo: Type,
+ initPrivateWithin: Symbol = NoSymbol) extends SingleDenotation {
- /** The privateWithin boundary, NoSymbol if no boundary is given. */
- def privateWithin: Symbol
+ // ------ Getting and setting fields -----------------------------
- /** The type info.
- * The info an instance of TypeType iff this is a type denotation
- */
- def info: Type
-
- /** The name with which the denoting symbol was created */
- def originalName =
- if (flags is ExpandedName) initial.asSymDenotation.name else name
-
- /** The encoded full path name of this denotation, where outer names and inner names
- * are separated by `separator` characters.
- * Never translates expansions of operators back to operator symbol.
- * Drops package objects.
- */
- def fullName(separator: Char)(implicit ctx: Context): Name =
- if (this == NoSymbol || owner == NoSymbol || owner.isEffectiveRoot) name
- else (effectiveOwner.enclosingClass.fullName(separator) :+ separator) ++ name
-
- /** `fullName` where `.' is the separator character */
- def fullName(implicit ctx: Context): Name = fullName('.')
+ def owner: Symbol = _owner
private[this] var _flags: FlagSet = initFlags
+ private[this] var _info: Type = initInfo
+ private[this] var _privateWithin: Symbol = initPrivateWithin
+ private[this] var _annotations: List[Annotation] = Nil
/** The flag set */
def flags: FlagSet = { ensureCompleted(); _flags }
/** Update the flag set */
- private[core] def flags_=(flags: FlagSet): Unit = { _flags = flags }
+ private[core] def flags_=(flags: FlagSet): Unit =
+ _flags = flags
/** Set given flags(s) of this denotation */
def setFlag(flags: FlagSet): Unit = { _flags |= flags }
- /** UnsSet given flags(s) of this denotation */
+ /** UnsSet given flags(s) of this denotation */
def resetFlag(flags: FlagSet): Unit = { _flags &~= flags }
- private[this] var _annotations: List[Annotation] = Nil
+ final def is(fs: FlagSet) = flags is fs
+ final def is(fs: FlagSet, butNot: FlagSet) = flags is (fs, butNot)
+ final def is(fs: FlagConjunction) = flags is fs
+ final def is(fs: FlagConjunction, butNot: FlagSet) = flags is (fs, butNot)
+
+ /** The type info.
+ * The info is an instance of TypeType iff this is a type denotation
+ * Uncompleted denotations set _info to a LazyType.
+ */
+ final def info: Type = _info match {
+ case _info: LazyType => completedInfo(_info)
+ case _ => _info
+ }
+
+ private def completedInfo(completer: LazyType): Type = {
+ if (_flags is CompletionStarted) throw new CyclicReference(symbol)
+ _flags |= CompletionStarted
+ completer.complete(this)
+ info
+ }
+
+ protected[core] def info_=(tp: Type) =
+ _info = tp
+
+ /** The denotation is completed: all attributes are fully defined */
+ final def isCompleted: Boolean = ! _info.isInstanceOf[LazyType]
+
+ /** Make sure this denotation is completed */
+ final def ensureCompleted(): Unit = info
+
+ /** The privateWithin boundary, NoSymbol if no boundary is given.
+ */
+ def privateWithin: Symbol = { ensureCompleted(); _privateWithin }
+
+ /** Set privateWithin. */
+ protected[core] def privateWithin_=(sym: Symbol): Unit =
+ _privateWithin = sym
/** The annotations of this denotation */
- def annotations: List[Annotation] = { ensureCompleted(); _annotations }
+ def annotations: List[Annotation] = {
+ ensureCompleted(); _annotations
+ }
/** Update the annotations of this denotation */
private[core] def annotations_=(annots: List[Annotation]): Unit = { _annotations = annots }
@@ -90,20 +122,33 @@ object SymDenotations {
case Nil => Nil
}
-// ----- completion ------------------------------
+ /** The symbols defined in this class when the class is not yet completed.
+ * @pre: this is a class
+ */
+ protected def preCompleteDecls: Scope = _info match {
+ case cinfo: LazyClassInfo => cinfo.decls
+ case cinfo: ClassInfo => cinfo.decls
+ }
- // The following 2 members are overridden by instances of isLazy
+ // ------ Names ----------------------------------------------
- /** The denotation is completed: all attributes are fully defined */
- def isCompleted = true
+ /** The name with which the denoting symbol was created */
+ def originalName =
+ if (flags is ExpandedName) initial.asSymDenotation.name else name
- /** Try to complete denotation. May throw `CyclicReference`. */
- protected[core] def tryComplete(): Unit = unsupported("tryComplete")
+ /** The encoded full path name of this denotation, where outer names and inner names
+ * are separated by `separator` characters.
+ * Never translates expansions of operators back to operator symbol.
+ * Drops package objects.
+ */
+ def fullName(separator: Char)(implicit ctx: Context): Name =
+ if (this == NoSymbol || owner == NoSymbol || owner.isEffectiveRoot) name
+ else (effectiveOwner.enclosingClass.fullName(separator) :+ separator) ++ name
- /** Make sure denotation is completed */
- final def ensureCompleted() = if (!isCompleted) tryComplete()
+ /** `fullName` where `.' is the separator character */
+ def fullName(implicit ctx: Context): Name = fullName('.')
-// ----- tests -------------------------------------------------
+ // ----- Tests -------------------------------------------------
/** Is this denotation a type? */
override def isType: Boolean = name.isTypeName
@@ -135,7 +180,11 @@ object SymDenotations {
* refers to a toplevel class or object that has no
* definition in the source or classfile from which it is loaded.
*/
- def exists(implicit ctx: Context) = true
+ override final def exists: Boolean = info ne NoType
+
+ /** Make denotation not exist */
+ final def markAbsent(): Unit =
+ _info = NoType
/** Is this symbol the root class or its companion object? */
def isRoot: Boolean = name.toTermName == nme.ROOT
@@ -245,9 +294,6 @@ object SymDenotations {
final def isNonValueClass(implicit ctx: Context): Boolean =
isClass && !isSubClass(defn.AnyValClass)
- /** Are the contents of this denotation invariant under the type map `f`? */
- def isInvariantUnder(f: Type => Type)(implicit ctx: Context) = info eq f(info)
-
/** Is this definition accessible whenever `that` symbol is accessible?
* Does not take into account status of protected members.
*/
@@ -292,9 +338,9 @@ object SymDenotations {
|enclosing ${ctx.enclClass.owner.showLocated} is not a subclass of
|${owner.showLocated} where target is defined""".stripMargin)
else if (!(isType || // allow accesses to types from arbitrary subclasses fixes #4737
- pre.widen.typeSymbol.isSubClassOrCompanion(cls) ||
- cls.isModuleClass &&
- pre.widen.typeSymbol.isSubClassOrCompanion(cls.linkedClass)))
+ pre.widen.typeSymbol.isSubClassOrCompanion(cls) ||
+ cls.isModuleClass &&
+ pre.widen.typeSymbol.isSubClassOrCompanion(cls.linkedClass)))
fail(
s"""Access to protected ${symbol.show} not permitted because
|prefix type ${pre.widen.show} does not conform to
@@ -302,7 +348,7 @@ object SymDenotations {
else true
}
- (pre == NoPrefix) || {
+ (pre == NoPrefix) || {
val boundary = accessBoundary(owner)
( (boundary.isTerm
@@ -322,18 +368,27 @@ object SymDenotations {
}
}
- // def isOverridable: Boolean = !!! need to enforce that classes cannot be redefined
- // def isSkolem: Boolean = ???
+ // def isOverridable: Boolean = !!! need to enforce that classes cannot be redefined
+ // def isSkolem: Boolean = ???
-// ------ access to related symbols ---------------------------------
+ // ------ access to related symbols ---------------------------------
/** The class implementing this module, NoSymbol if not applicable. */
- final def moduleClass(implicit ctx: Context): Symbol =
- if (this.isModuleVal) info.typeSymbol else NoSymbol
+ final def moduleClass: Symbol = _info match {
+ case info: TypeRefBySym if isModuleVal => info.fixedSym
+ case info: LazyModuleInfo => info.mclass
+ case _ => NoSymbol
+ }
/** The module implemented by this module class, NoSymbol if not applicable. */
- final def sourceModule(implicit ctx: Context): Symbol =
- if (this.isModuleClass) this.asClass.selfType.termSymbol else NoSymbol
+ final def sourceModule: Symbol = _info match {
+ case ClassInfo(_, _, _, _, selfType: TermRefBySym) if isModuleClass =>
+ selfType.fixedSym
+ case info: LazyModuleClassInfo =>
+ info.modul
+ case _ =>
+ NoSymbol
+ }
/** The chain of owners of this denotation, starting with the denoting symbol itself */
final def ownersIterator(implicit ctx: Context) = new Iterator[Symbol] {
@@ -346,7 +401,7 @@ object SymDenotations {
}
}
- /** If this is a package object or its implementing class, its owner,
+ /** If this is a package object or its implementing class, its owner,
* otherwise the denoting symbol.
*/
final def skipPackageObject(implicit ctx: Context): Symbol =
@@ -414,7 +469,7 @@ object SymDenotations {
* @param inClass 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 = {
+ final def matchingSymbol(inClass: Symbol, site: Type)(implicit ctx: Context): Symbol = {
var denot = inClass.info.nonPrivateDecl(name)
if (denot.isTerm) {
val targetType = site.memberInfo(symbol)
@@ -453,7 +508,7 @@ object SymDenotations {
/** The primary constructor of a class or trait, NoSymbol if not applicable. */
def primaryConstructor(implicit ctx: Context): Symbol = NoSymbol
- // ----- type-related ------------------------------------------------
+ // ----- type-related ------------------------------------------------
/** The type parameters of a class symbol, Nil for all other symbols */
def typeParams(implicit ctx: Context): List[TypeSymbol] = Nil
@@ -482,51 +537,49 @@ object SymDenotations {
else if (this is Contravariant) -1
else 0
- // ----- copies ------------------------------------------------------
+ // ----- copies ------------------------------------------------------
override protected def newLikeThis(s: Symbol, i: Type): SingleDenotation = new UniqueRefDenotation(s, i, validFor)
/** Copy this denotation, overriding selective fields */
- def copySym(
- sym: Symbol,
- owner: Symbol = this.owner,
- name: Name = this.name,
- initFlags: FlagSet = this.flags,
- privateWithin: Symbol = this.privateWithin,
- info: Type = this.info) =
- CompleteSymDenotation(sym, owner, name, initFlags, info, privateWithin)
+ def copySymDenotation(
+ symbol: Symbol = this.symbol,
+ owner: Symbol = this.owner,
+ name: Name = this.name,
+ initFlags: FlagSet = this.flags,
+ info: Type = this.info,
+ privateWithin: Symbol = this.privateWithin,
+ annotations: List[Annotation] = this.annotations)(implicit ctx: Context) =
+ {
+ val d = ctx.SymDenotation(symbol, owner, name, initFlags, info, privateWithin)
+ d.annotations = annotations
+ d
+ }
}
/** The contents of a class definition during a period
* Note: important to leave initctx non-implicit, and to check that it is not
* retained after object construction.
*/
- abstract class ClassDenotation(initFlags: FlagSet)(initctx: Context)
- extends SymDenotation(initFlags) {
+ class ClassDenotation private[SymDenotations] (
+ symbol: Symbol,
+ _owner: Symbol,
+ name: Name,
+ initFlags: FlagSet,
+ initInfo: Type,
+ initPrivateWithin: Symbol = NoSymbol)
+ extends SymDenotation(symbol, _owner, name, initFlags, initInfo, initPrivateWithin) {
+
import NameFilter._
import util.LRU8Cache
-// ----- denotation fields and accessors ------------------------------
-
- override val symbol: ClassSymbol
-
- /** The parent types of this class.
- * These are all normalized to be TypeRefs by moving any refinements
- * to be member definitions of the class itself. */
- def parents: List[TypeRef]
-
- /** The type of `this` in this class */
- def selfType: Type
+ // ----- denotation fields and accessors ------------------------------
- /** The symbols defined directly in this class */
- def decls: Scope
+ /** The symbol asserted to have type ClassSymbol */
+ def classSymbol: ClassSymbol = symbol.asInstanceOf[ClassSymbol]
- def name: TypeName
-
- override val info = {
- implicit val ctx = initctx
- ClassInfo(owner.thisType, this)
- }
+ /** The info asserted to have type ClassInfo */
+ def classInfo(implicit ctx: Context): ClassInfo = super.info.asInstanceOf[ClassInfo]
private[this] var _typeParams: List[TypeSymbol] = _
@@ -536,14 +589,10 @@ object SymDenotations {
if (tparams != null) tparams else computeTypeParams
}
- /** The symbols defined in this class when the class is not yet completed.
- */
- protected def preCompleteDecls: Scope
-
private def computeTypeParams(implicit ctx: Context): List[TypeSymbol] =
(preCompleteDecls.toList filter (_ is TypeParam)).asInstanceOf[List[TypeSymbol]]
-// ------ class-specific operations -----------------------------------
+ // ------ class-specific operations -----------------------------------
private[this] var _thisType: Type = null
@@ -557,7 +606,7 @@ object SymDenotations {
if (isPackageClass && !isRoot)
TermRef(owner.thisType, name.toTermName)
else
- ThisType(symbol)
+ ThisType(classSymbol)
private[this] var _typeConstructor: TypeRef = null
@@ -593,7 +642,7 @@ object SymDenotations {
case _ =>
to
}
- _baseClasses = symbol :: addParentBaseClasses(parents, Nil)
+ _baseClasses = classSymbol :: addParentBaseClasses(classInfo.classParents, Nil)
_superClassBits = ctx.uniqueBits.findEntryOrUpdate(seen.toImmutable)
}
@@ -605,7 +654,7 @@ object SymDenotations {
/** The base classes of this class in linearization order,
* with the class itself as first element.
*/
- def baseClasses(implicit ctx: Context): List[ClassSymbol] = {
+ def baseClasses(implicit ctx: Context): List[ClassSymbol] = {
if (_baseClasses == null) computeSuperClassBits
_baseClasses
}
@@ -624,12 +673,12 @@ object SymDenotations {
private def computeDefinedFingerPrint(implicit ctx: Context): FingerPrint = {
var bits = newNameFilter
- var e = decls.lastEntry
+ var e = info.decls.lastEntry
while (e != null) {
includeName(bits, name)
e = e.prev
}
- var ps = parents
+ var ps = classInfo.classParents
while (ps.nonEmpty) {
val parent = ps.head.typeSymbol
parent.denot match {
@@ -650,13 +699,14 @@ object SymDenotations {
if (_memberCache == null) _memberCache = new LRU8Cache
_memberCache
}
+
/** Enter a symbol in current scope.
* Note: We require that this does not happen after the first time
* someone does a findMember on a subclass.
*/
def enter(sym: Symbol)(implicit ctx: Context) = {
require(!(this is Frozen))
- decls enter sym
+ info.decls enter sym
if (_definedFingerPrint != null)
includeName(_definedFingerPrint, sym.name)
if (_memberCache != null)
@@ -669,7 +719,7 @@ object SymDenotations {
*/
def delete(sym: Symbol)(implicit ctx: Context) = {
require(!(this is Frozen))
- decls unlink sym
+ info.decls unlink sym
if (_definedFingerPrint != null)
computeDefinedFingerPrint
if (_memberCache != null)
@@ -685,9 +735,9 @@ object SymDenotations {
var denots: DenotationSet = memberCache lookup name
if (denots == null) {
if (containsName(definedFingerPrint, name)) {
- val ownDenots = decls.denotsNamed(name)
+ val ownDenots = info.decls.denotsNamed(name)
denots = ownDenots
- var ps = parents
+ var ps = classInfo.classParents
while (ps.nonEmpty) {
val parentSym = ps.head.typeSymbol
parentSym.denot match {
@@ -720,13 +770,13 @@ object SymDenotations {
baseTypeOf(tp1) & baseTypeOf(tp2)
case OrType(tp1, tp2) =>
baseTypeOf(tp1) | baseTypeOf(tp2)
- case tp @ ClassInfo(pre, classd) =>
+ case tp: ClassInfo =>
def reduce(bt: Type, ps: List[Type]): Type = ps match {
case p :: ps1 => reduce(bt & baseTypeOf(p), ps1)
case _ => bt
}
- if (classd.symbol == symbol) tp.typeConstructor // was: typeTemplate
- else reduce(NoType, classd.parents).substThis(classd.symbol, tp.prefix)
+ if (tp.cls eq symbol) tp.typeConstructor
+ else tp.rebase(reduce(NoType, tp.classParents))
}
if (symbol.isStatic) symbol.typeConstructor
@@ -757,25 +807,25 @@ object SymDenotations {
case Some(names) =>
names
case _ =>
- val inheritedNames = (parents flatMap (_.memberNames(thisType, keepOnly))).toSet
- val ownNames = decls.iterator map (_.name)
+ val inheritedNames = (classInfo.classParents flatMap (_.memberNames(thisType, keepOnly))).toSet
+ val ownNames = info.decls.iterator map (_.name)
val candidates = inheritedNames ++ ownNames
val names = candidates filter (keepOnly(thisType, _))
memberNamesCache = memberNamesCache.updated(keepOnly, names)
names
- }
+ }
private[this] var fullNameCache: Map[Char, Name] = Map()
override final def fullName(separator: Char)(implicit ctx: Context): Name =
fullNameCache get separator match {
- case Some(fn) =>
- fn
- case _ =>
- val fn = super.fullName(separator)
- fullNameCache = fullNameCache.updated(separator, fn)
- fn
- }
+ case Some(fn) =>
+ fn
+ case _ =>
+ val fn = super.fullName(separator)
+ fullNameCache = fullNameCache.updated(separator, fn)
+ fn
+ }
// to avoid overloading ambiguities
override def fullName(implicit ctx: Context): Name = super.fullName
@@ -783,198 +833,91 @@ object SymDenotations {
override def primaryConstructor(implicit ctx: Context): Symbol = {
val cname =
if (this is Trait | ImplClass) nme.TRAIT_CONSTRUCTOR else nme.CONSTRUCTOR
- decls.denotsNamed(cname).first.symbol
- }
-
- override def isInvariantUnder(f: Type => Type)(implicit ctx: Context) =
- (parents.mapConserve(f) eq parents) &&
- (f(selfType) eq selfType) &&
- (decls forall (_.isInvariantUnder(f)))
-
- def copyClass(
- sym: ClassSymbol,
- owner: Symbol = this.owner,
- name: TypeName = this.name,
- initFlags: FlagSet = this.flags,
- privateWithin: Symbol = this.privateWithin,
- parents: List[TypeRef] = this.parents,
- selfType: Type = this.selfType,
- decls: Scope = this.decls)(implicit ctx: Context) =
- new CompleteClassDenotation(sym, owner, name, initFlags, parents, privateWithin, selfType, decls)(ctx)
- }
-
-// -------- Concrete classes for instantiating denotations --------------------------
-
- class CompleteSymDenotation(
- val symbol: Symbol,
- val owner: Symbol,
- val name: Name,
- initFlags: FlagSet,
- val info: Type,
- val privateWithin: Symbol
- ) extends SymDenotation(initFlags)
-
- def CompleteSymDenotation(symbol: Symbol, owner: Symbol, name: Name, initFlags: FlagSet,
- info: Type, privateWithin: Symbol = NoSymbol) =
- new CompleteSymDenotation(symbol, owner, name, initFlags, info, privateWithin)
-
- class LazySymDenotation(
- val symbol: Symbol,
- val owner: Symbol,
- val name: Name,
- initFlags: FlagSet,
- var completer: SymCompleter
- ) extends SymDenotation(initFlags) with isLazy[LazySymDenotation] {
-
- final override def exists(implicit ctx: Context) =
- !isModuleVal || moduleClass.denot.exists
-
- private[this] var _info: Type = _
- protected[core] def info_=(tp: Type) = if (_info == null) _info = tp
- override def info = { if (info == null) tryComplete(); _info }
- }
-
- def LazySymDenotation(symbol: Symbol, owner: Symbol, name: Name, initFlags: FlagSet,
- completer: SymCompleter) =
- new LazySymDenotation(symbol, owner, name, initFlags, completer)
-
- class CompleteClassDenotation(
- val symbol: ClassSymbol,
- val owner: Symbol,
- val name: TypeName,
- initFlags: FlagSet,
- val parents: List[TypeRef],
- val privateWithin: Symbol,
- optSelfType: Type,
- val decls: Scope)(initctx: Context)
- extends ClassDenotation(initFlags)(initctx) {
- val selfType = if (optSelfType == NoType) typeConstructor(initctx) else optSelfType
- final def preCompleteDecls = decls
- }
-
- def CompleteClassDenotation(
- symbol: ClassSymbol, owner: Symbol, name: TypeName, initFlags: FlagSet, parents: List[TypeRef],
- privateWithin: Symbol = NoSymbol,
- optSelfType: Type = NoType,
- decls: Scope = newScope,
- assocFile: AbstractFile = null)(implicit ctx: Context) =
- new CompleteClassDenotation(symbol, owner, name, initFlags, parents,
- privateWithin, optSelfType, decls)(ctx)
-
- class LazyClassDenotation(
- val symbol: ClassSymbol,
- val owner: Symbol,
- val name: TypeName,
- initFlags: FlagSet,
- var completer: ClassCompleter
- )(initctx: Context) extends ClassDenotation(initFlags)(initctx) with isLazy[LazyClassDenotation] {
-
- private[this] var _parents: List[TypeRef] = null
- private[this] var _selfType: Type = null
- private[this] var _decls: Scope = null
-
- protected[core] def parents_=(ps: List[TypeRef]) = if (_parents == null) _parents = ps
- protected[core] def selfType_=(tp: Type) = if (_selfType == null) _selfType = tp
- protected[core] def decls_=(sc: Scope) = if (_decls == null) _decls = sc
-
- final def parents: List[TypeRef] = { if (_parents == null) tryComplete(); _parents }
- def selfType: Type = { if (_selfType == null) tryComplete(); _selfType }
- final def preCompleteDecls = { if (_decls == null) tryComplete(); _decls }
- final def decls: Scope = { ensureCompleted(); _decls }
- // cannot check on decls because decls might be != null even if class is not completed
-
- final override def exists(implicit ctx: Context) = { ensureCompleted(); _parents != null }
+ info.decls.denotsNamed(cname).first.symbol
+ }
}
- def LazyClassDenotation(
- symbol: ClassSymbol, owner: Symbol, name: TypeName, initFlags: FlagSet,
- completer: ClassCompleter, assocFile: AbstractFile = null)(implicit ctx: Context) =
- new LazyClassDenotation(symbol, owner, name, initFlags, completer)(ctx)
-
- object NoDenotation extends SymDenotation(EmptyFlags) {
+ object NoDenotation extends SymDenotation(
+ NoSymbol, NoSymbol, "<none>".toTermName, EmptyFlags, NoType) {
override def isTerm = false
override def isType = false
- override def symbol: Symbol = NoSymbol
override def owner: Symbol = throw new AssertionError("NoDenotation.owner")
- override def name: Name = "<none>".toTermName
- override def info: Type = NoType
- override def privateWithin = NoSymbol
- override def exists(implicit ctx: Context) = false
}
-// ---- Completion --------------------------------------------------------
-
- trait isLazy[Denot <: SymDenotation] extends SymDenotation { this: Denot =>
-
- protected def completer: Completer[Denot]
- protected def completer_= (c: Completer[Denot])
+ // ---- Completion --------------------------------------------------------
- override def isCompleted = completer == null
+ /** Instances of LazyType are carried by uncompleted symbols.
+ * Note: LazyTypes double up as (constant) functions from Symbol and
+ * from (TermSymbol, ClassSymbol) to LazyType. That way lazy types can be
+ * directly passed to symbol creation methods in Symbols that demand instances
+ * of these types.
+ */
+ abstract class LazyType extends UncachedGroundType
+ with (Symbol => LazyType)
+ with ((TermSymbol, ClassSymbol) => LazyType) {
- override protected[core] def tryComplete(): Unit =
- try {
- if (flags is Locked) throw new CyclicReference(symbol)
- setFlag(Locked)
- val c = completer
- if (c == null) throw new CompletionError(this)
- completer = null // set completer to null to avoid space leaks
- // and to make any subsequent completion attempt a CompletionError
- c(this)
- } finally {
- flags &~= Locked
- }
+ /** Sets all missing fields of given denotation */
+ def complete(denot: SymDenotation): Unit
- private[this] var _privateWithin: Symbol = _
- def privateWithin: Symbol = { if (_privateWithin == null) tryComplete(); _privateWithin }
- protected[core] def privateWithin_=(sym: Symbol): Unit = { _privateWithin = sym }
+ def apply(sym: Symbol) = this
+ def apply(module: TermSymbol, modcls: ClassSymbol) = this
}
- /** When called, complete denotation, setting all its properties */
- type Completer[Denot <: SymDenotation] = Denot => Unit
- type SymCompleter = Completer[LazySymDenotation]
- type ClassCompleter = Completer[LazyClassDenotation]
+ /** A lazy type for classes that contains an initial pre-complete scope.
+ * Typically this is for type parameters
+ */
+ abstract class LazyClassInfo(val decls: Scope) extends LazyType
- class ModuleCompleter(cctx: CondensedContext) extends SymCompleter {
- implicit protected def ctx: Context = cctx
- def apply(denot: LazySymDenotation): Unit = {
- val from = denot.moduleClass.denot.asInstanceOf[LazyClassDenotation]
+ /** A lazy type for module classes that points back to the source module.
+ * Needed so that `sourceModule` works before completion.
+ */
+ abstract class LazyModuleClassInfo(val modul: TermSymbol) extends LazyClassInfo(newScope)
+
+ /** A lazy type for modules that points to the source module class.
+ * Needed so that `moduleClass` works before completion.
+ * Completion of modules is always completion of the underlying
+ * module class, followed by copying the relevant fields to the module.
+ */
+ class LazyModuleInfo(val mclass: ClassSymbol)(implicit cctx: CondensedContext) extends LazyType {
+ def complete(denot: SymDenotation): Unit = {
+ val from = denot.moduleClass.denot.asClass
denot.setFlag(from.flags.toTermFlags & RetainedModuleFlags)
- denot.privateWithin = from.privateWithin
denot.annotations = from.annotations filter (_.appliesToModule)
+ denot.info = TypeRef(denot.owner.thisType, mclass)
+ denot.privateWithin = from.privateWithin
}
}
/** A completer for missing references */
- class StubCompleter(cctx: CondensedContext) extends ClassCompleter {
- implicit protected def ctx: Context = cctx
+ class StubInfo()(implicit cctx: CondensedContext) extends LazyType {
- def initializeToDefaults(denot: LazyClassDenotation) = {
- // todo: initialize to errors instead?
+ def initializeToDefaults(denot: SymDenotation) = {
+ denot.info = denot match {
+ case denot: ClassDenotation =>
+ ClassInfo(denot.owner.thisType, denot.classSymbol, Nil, EmptyScope)
+ case _ =>
+ ErrorType
+ }
denot.privateWithin = NoSymbol
- denot.parents = Nil
- denot.selfType = denot.typeConstructor
- denot.decls = EmptyScope
}
- def apply(denot: LazyClassDenotation): Unit = {
+ def complete(denot: SymDenotation): Unit = {
val sym = denot.symbol
val file = sym.associatedFile
val (location, src) =
if (file != null) (s" in $file", file.toString)
else ("", "the signature")
- ctx.error(
- s"""|bad symbolic reference. A signature$location refers to ${ctx.showDetailed(denot.name)}
+ cctx.error(
+ s"""|bad symbolic reference. A signature$location refers to ${cctx.showDetailed(denot.name)}
|in ${denot.owner.showKind} ${denot.owner.showFullName} which is not available.
|It may be completely missing from the current classpath, or the version on
|the classpath might be incompatible with the version used when compiling $src.""".stripMargin)
- if (ctx.settings.debug.value) (new Throwable).printStackTrace
+ if (cctx.settings.debug.value) (new Throwable).printStackTrace
initializeToDefaults(denot)
}
}
- class CompletionError(denot: SymDenotation) extends Error("Trying to access missing symbol ${denot.symbol.fullName}")
-
-// ---- Name filter --------------------------------------------------------
+ // ---- Name filter --------------------------------------------------------
object NameFilter {
final val WordSizeLog = 6
@@ -999,7 +942,4 @@ object SymDenotations {
def newNameFilter: FingerPrint = new Array[Long](DefinedNamesWords)
}
-
- implicit def toFlagSet(denot: SymDenotation): FlagSet = denot.flags
-
}
diff --git a/src/dotty/tools/dotc/core/SymbolLoaders.scala b/src/dotty/tools/dotc/core/SymbolLoaders.scala
index 2e37d8124..85fb8037d 100644
--- a/src/dotty/tools/dotc/core/SymbolLoaders.scala
+++ b/src/dotty/tools/dotc/core/SymbolLoaders.scala
@@ -26,14 +26,14 @@ class SymbolLoaders {
/** Enter class with given `name` into scope of `owner`.
*/
def enterClass(owner: Symbol, name: PreName, completer: SymbolLoader, flags: FlagSet = EmptyFlags)(implicit ctx: Context): Symbol = {
- val cls = ctx.newLazyClassSymbol(owner, name.toTypeName, flags, completer, assocFile = completer.sourceFileOrNull)
+ val cls = ctx.newClassSymbol(owner, name.toTypeName, flags, completer, assocFile = completer.sourceFileOrNull)
enterIfNew(owner, cls, completer)
}
/** Enter module with given `name` into scope of `owner`.
*/
def enterModule(owner: Symbol, name: PreName, completer: SymbolLoader, flags: FlagSet = EmptyFlags)(implicit ctx: Context): Symbol = {
- val module = ctx.newLazyModuleSymbols(owner, name.toTermName, flags, completer, assocFile = completer.sourceFileOrNull)._1
+ val module = ctx.newModuleSymbol(owner, name.toTermName, flags, completer, assocFile = completer.sourceFileOrNull)
enterIfNew(owner, module, completer)
}
@@ -63,7 +63,7 @@ class SymbolLoaders {
return NoSymbol
}
}
- ctx.newLazyModuleSymbols(owner, pname, PackageCreationFlags, completer)._1.entered
+ ctx.newModuleSymbol(owner, pname, PackageCreationFlags, completer).entered
}
/** Enter class and module with given `name` into scope of `owner`
@@ -119,16 +119,12 @@ class SymbolLoaders {
/** Load contents of a package
*/
- class PackageLoader(classpath: ClassPath)(cctx: CondensedContext) extends SymbolLoader {
- implicit val ctx: Context = cctx
+ class PackageLoader(classpath: ClassPath)(implicit val cctx: CondensedContext) extends SymbolLoader {
protected def description = "package loader " + classpath.name
- protected def doLoad(root: LazyClassDenotation) = doComplete(root)
-
- protected def doComplete(root: LazyClassDenotation) {
+ protected override def doComplete(root: SymDenotation) {
assert(root.isPackageClass, root)
- root.parents = Nil
- root.decls = newScope
+ root.info = ClassInfo(root.owner.thisType, root.symbol.asClass, Nil, newScope)
if (!root.isRoot) {
for (classRep <- classpath.classes) {
initializeFromClassPath(root.symbol, classRep)
@@ -136,9 +132,8 @@ class SymbolLoaders {
}
if (!root.isEmptyPackage) {
for (pkg <- classpath.packages) {
- enterPackage(root.symbol, pkg.name, new PackageLoader(pkg)(cctx))
+ enterPackage(root.symbol, pkg.name, new PackageLoader(pkg))
}
-
openPackageModule(root.symbol)
}
}
@@ -151,11 +146,11 @@ class SymbolLoaders {
* Todo: consider factoring out behavior from TopClassCompleter/SymbolLoader into
* supertrait SymLoader
*/
-abstract class SymbolLoader extends ClassCompleter {
- implicit val ctx: Context
+abstract class SymbolLoader extends LazyType {
+ implicit val cctx: CondensedContext
/** Load source or class file for `root`, return */
- protected def doComplete(root: LazyClassDenotation): Unit
+ protected def doComplete(root: SymDenotation): Unit
def sourceFileOrNull: AbstractFile = null
@@ -164,48 +159,48 @@ abstract class SymbolLoader extends ClassCompleter {
*/
protected def description: String
- override def apply(root: LazyClassDenotation) = {
+ override def complete(root: SymDenotation): Unit = {
def signalError(ex: Exception) {
- if (ctx.settings.debug.value) ex.printStackTrace()
+ if (cctx.settings.debug.value) ex.printStackTrace()
val msg = ex.getMessage()
- ctx.error(
+ cctx.error(
if (msg eq null) "i/o error while loading " + root.name
else "error while loading " + root.name + ", " + msg)
}
try {
val start = currentTime
doComplete(root)
- ctx.informTime("loaded " + description, start)
+ cctx.informTime("loaded " + description, start)
} catch {
case ex: IOException =>
signalError(ex)
} finally {
- root.linkedClass.denot match {
- case companion: LazyClassDenotation => companion.completer = null
- }
+ def postProcess(denot: SymDenotation) =
+ if (!denot.isCompleted) denot.markAbsent()
+ postProcess(root)
+ postProcess(root.linkedClass.denot)
}
}
}
-class ClassfileLoader(val classfile: AbstractFile)(cctx: CondensedContext) extends SymbolLoader {
- implicit val ctx: Context = cctx
+class ClassfileLoader(val classfile: AbstractFile)(implicit val cctx: CondensedContext) extends SymbolLoader {
override def sourceFileOrNull: AbstractFile = classfile
protected def description = "class file "+ classfile.toString
- def rootDenots(rootDenot: LazyClassDenotation): (LazyClassDenotation, LazyClassDenotation) = {
+ def rootDenots(rootDenot: ClassDenotation): (ClassDenotation, ClassDenotation) = {
val linkedDenot = rootDenot.linkedClass.denot match {
- case d: LazyClassDenotation => d
- case d => throw new FatalError(s"linked class denot $d of $rootDenot is expected to be a LazyClassDenot, but is a ${d.getClass}")
+ case d: ClassDenotation => d
+ case d => throw new FatalError(s"linked class denot $d of $rootDenot is expected to be a ClassDenotation, but is a ${d.getClass}")
}
- if (rootDenot.isModule) (linkedDenot, rootDenot)
+ if (rootDenot.isModuleClass) (linkedDenot, rootDenot)
else (rootDenot, linkedDenot)
}
- protected def doComplete(root: LazyClassDenotation) {
- val (classRoot, moduleRoot) = rootDenots(root)
- new ClassfileParser(classfile, classRoot, moduleRoot)(cctx).run()
+ protected def doComplete(root: SymDenotation) {
+ val (classRoot, moduleRoot) = rootDenots(root.asClass)
+ new ClassfileParser(classfile, classRoot, moduleRoot).run()
}
}
/*
diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala
index 2aec15894..c37bd0bdc 100644
--- a/src/dotty/tools/dotc/core/Symbols.scala
+++ b/src/dotty/tools/dotc/core/Symbols.scala
@@ -19,110 +19,189 @@ import io.AbstractFile
/** Creation methods for symbols */
trait Symbols { this: Context =>
-// ---- Fundamental symbol creation methods ----------------------------------
+// ---- Factory methods for symbol creation ----------------------
+//
+// All symbol creations should be done via the next two methods.
- def newLazySymbol[N <: Name](owner: Symbol, name: N, initFlags: FlagSet, completer: SymCompleter, coord: Coord = NoCoord) =
- new Symbol(coord, new LazySymDenotation(_, owner, name, initFlags, completer)) {
- type ThisName = N
- }
+ /** Create a symbol without a denotation.
+ * Note this uses a cast instead of a direct type refinement because
+ * it's debug-friendlier not to create an anonymous class here.
+ */
+ def newNakedSymbol[N <: Name](coord: Coord = NoCoord): Symbol { type ThisName = N } =
+ new Symbol(coord).asInstanceOf
- def newLazyClassSymbol(owner: Symbol, name: TypeName, initFlags: FlagSet, completer: ClassCompleter, assocFile: AbstractFile = null, coord: Coord = NoCoord) =
- new ClassSymbol(coord, new LazyClassDenotation(_, owner, name, initFlags, completer)(this), assocFile)
+ /** Create a class symbol without a denotation. */
+ def newNakedClassSymbol(coord: Coord = NoCoord, assocFile: AbstractFile = null) =
+ new ClassSymbol(coord, assocFile)
- def newLazyModuleSymbols(owner: Symbol,
- name: TermName,
+// ---- Symbol creation methods ----------------------------------
+
+ /** Create a symbol from a function producing its denotation */
+ def newSymbolDenoting[N <: Name](denotFn: Symbol => SymDenotation, coord: Coord = NoCoord): Symbol { type ThisName = N } = {
+ val sym = newNakedSymbol[N](coord)
+ sym.denot = denotFn(sym)
+ sym
+ }
+
+ /** Create a symbol from its fields (info may be lazy) */
+ def newSymbol[N <: Name](
+ owner: Symbol,
+ name: N,
flags: FlagSet,
- completer: ClassCompleter,
- assocFile: AbstractFile = null,
- coord: Coord = NoCoord): (TermSymbol, ClassSymbol)
- = {
- val module = newLazySymbol(
- owner, name, flags | ModuleCreationFlags, new ModuleCompleter(condensed), coord)
- val modcls = newLazyClassSymbol(
- owner, name.toTypeName, flags | ModuleClassCreationFlags, completer, assocFile, coord)
- module.denot.asInstanceOf[LazySymDenotation].info =
- TypeRef(owner.thisType(ctx), modcls)
- modcls.denot.asInstanceOf[LazyClassDenotation].selfType =
- TermRef(owner.thisType, module)
- (module, modcls)
+ info: Type,
+ privateWithin: Symbol = NoSymbol,
+ coord: Coord = NoCoord): Symbol { type ThisName = N } = {
+ val sym = newNakedSymbol[N](coord)
+ val denot = SymDenotation(sym, owner, name, flags, info, privateWithin)
+ sym.denot = denot
+ sym
}
- def newSymbol[N <: Name](owner: Symbol, name: N, flags: FlagSet, info: Type, privateWithin: Symbol = NoSymbol, coord: Coord = NoCoord) =
- new Symbol(coord, CompleteSymDenotation(_, owner, name, flags, info, privateWithin)) {
- type ThisName = N
- }
+ /** Create a class symbol from a function producing its denotation */
+ def newClassSymbolDenoting(denotFn: ClassSymbol => SymDenotation, coord: Coord = NoCoord, assocFile: AbstractFile = null): ClassSymbol = {
+ val cls = newNakedClassSymbol(coord, assocFile)
+ cls.denot = denotFn(cls)
+ cls
+ }
+ /** Create a class symbol from its non-info fields and a function
+ * producing its info (the info may be lazy).
+ */
def newClassSymbol(
owner: Symbol,
name: TypeName,
flags: FlagSet,
- parents: List[TypeRef],
+ infoFn: ClassSymbol => Type,
privateWithin: Symbol = NoSymbol,
- optSelfType: Type = NoType,
- decls: Scope = newScope,
- assocFile: AbstractFile = null,
- coord: Coord = NoCoord)
- =
- new ClassSymbol(coord, new CompleteClassDenotation(
- _, owner, name, flags, parents, privateWithin, optSelfType, decls)(this), assocFile)
+ coord: Coord = NoCoord,
+ assocFile: AbstractFile = null): ClassSymbol
+ = {
+ val cls = newNakedClassSymbol(coord, assocFile)
+ val denot = SymDenotation(cls, owner, name, flags, infoFn(cls))
+ cls.denot = denot
+ cls
+ }
- def newModuleSymbols(
+ /** Create a class symbol from its non-info fields and the fields of its info. */
+ def newCompleteClassSymbol(
owner: Symbol,
- name: TermName,
+ name: TypeName,
flags: FlagSet,
- classFlags: FlagSet,
parents: List[TypeRef],
- privateWithin: Symbol = NoSymbol,
decls: Scope = newScope,
- assocFile: AbstractFile = null,
- coord: Coord = NoCoord): (TermSymbol, ClassSymbol)
+ optSelfType: Type = NoType,
+ privateWithin: Symbol = NoSymbol,
+ coord: Coord = NoCoord,
+ assocFile: AbstractFile = null): ClassSymbol =
+ newClassSymbol(
+ owner, name, flags,
+ ClassInfo(owner.thisType, _, parents, decls, optSelfType),
+ privateWithin, coord, assocFile)
+
+ /** Create a module symbol with associated module class
+ * from its non-info fields and a function producing the info
+ * of the module class (this info may be lazy).
+ * @param flags The combined flags of the module and the module class
+ * These are masked with RetainedModuleFlags/RetainedModuleClassFlags.
+ */
+ def newModuleSymbol(
+ owner: Symbol,
+ name: TermName,
+ flags: FlagSet,
+ infoFn: (TermSymbol, ClassSymbol) => Type,
+ privateWithin: Symbol = NoSymbol,
+ coord: Coord = NoCoord,
+ assocFile: AbstractFile = null): TermSymbol
= {
- val module = newLazySymbol(
- owner, name, flags | ModuleCreationFlags,
- new ModuleCompleter(condensed), coord)
- val modcls = newClassSymbol(
- owner, name.toTypeName, classFlags | ModuleClassCreationFlags, parents, privateWithin,
- optSelfType = TermRef(owner.thisType, module),
- decls, assocFile, coord)
- module.denot.asInstanceOf[LazySymDenotation].info =
- TypeRef(owner.thisType, modcls)
- (module, modcls)
+ val base = owner.thisType
+ val module = newNakedSymbol[TermName](coord)
+ val modcls = newNakedClassSymbol(coord, assocFile)
+ val cdenot = SymDenotation(
+ modcls, owner, name.toTypeName,
+ flags & RetainedModuleClassFlags | ModuleClassCreationFlags,
+ infoFn(module, modcls), privateWithin)
+ val mdenot = SymDenotation(
+ module, owner, name,
+ flags & RetainedModuleFlags | ModuleCreationFlags,
+ if (cdenot.isCompleted) TypeRef(owner.thisType, modcls)
+ else new LazyModuleInfo(modcls)(condensed))
+ module.denot = mdenot
+ modcls.denot = cdenot
+ module
}
+ /** Create a module symbol with associated module class
+ * from its non-info fields and the fields of the module class info.
+ * @param flags The combined flags of the module and the module class
+ * These are masked with RetainedModuleFlags/RetainedModuleClassFlags.
+ */
+ def newCompleteModuleSymbol(
+ owner: Symbol,
+ name: TermName,
+ flags: FlagSet,
+ parents: List[TypeRef],
+ decls: Scope,
+ privateWithin: Symbol = NoSymbol,
+ coord: Coord = NoCoord,
+ assocFile: AbstractFile = null): TermSymbol =
+ newModuleSymbol(
+ owner, name, flags,
+ (module, modcls) => ClassInfo(
+ owner.thisType, modcls, parents, decls, TermRef(owner.thisType, module)),
+ privateWithin, coord, assocFile)
+
+ /** Create a package symbol with associated package class
+ * from its non-info fields and a lazy type for loading the package's members.
+ */
+ def newPackageSymbol(
+ owner: Symbol,
+ name: TermName,
+ info: LazyType): TermSymbol =
+ newModuleSymbol(owner, name, PackageCreationFlags, info)
+
+ /** Create a package symbol with associated package class
+ * from its non-info fields and the fields of the package class info.
+ */
+ def newCompletePackageSymbol(
+ owner: Symbol,
+ name: TermName,
+ flags: FlagSet = EmptyFlags,
+ decls: Scope = newScope): TermSymbol =
+ newCompleteModuleSymbol(owner, name, flags | PackageCreationFlags, Nil, decls)
+
+
+ /** Create a stub symbol that will issue a missing reference error
+ * when attempted to be completed.
+ */
def newStubSymbol(owner: Symbol, name: Name, file: AbstractFile = null): Symbol = {
- def stub = new StubCompleter(ctx.condensed)
+ def stub = new StubInfo()(condensed)
name match {
- case name: TermName => ctx.newLazyModuleSymbols(owner, name, EmptyFlags, stub, file)._1
- case name: TypeName => ctx.newLazyClassSymbol(owner, name, EmptyFlags, stub, file)
+ case name: TermName =>
+ newModuleSymbol(owner, name, EmptyFlags, stub, assocFile = file)
+ case name: TypeName =>
+ newClassSymbol(owner, name, EmptyFlags, stub, assocFile = file)
}
}
-// ---- Derived symbol creation methods -------------------------------------
-
- def newLazyPackageSymbols(owner: Symbol, name: TermName, completer: ClassCompleter) =
- newLazyModuleSymbols(owner, name, PackageCreationFlags, completer)
-
- def newPackageSymbols(
- owner: Symbol,
- name: TermName,
- decls: Scope = newScope) =
- newModuleSymbols(
- owner, name, PackageCreationFlags, PackageCreationFlags, Nil, NoSymbol, decls)
-
+ /** Create the local template dummy of given class `cls`. */
def newLocalDummy(cls: Symbol, coord: Coord = NoCoord) =
newSymbol(cls, nme.localDummyName(cls), EmptyFlags, NoType)
+ /** Create an import symbol pointing back to given qualifier `expr`. */
def newImportSymbol(expr: Shared[Type], coord: Coord = NoCoord) =
newSymbol(NoSymbol, nme.IMPORT, EmptyFlags, ImportType(expr), coord = coord)
+ /** Create a class constructor symbol for given class `cls`. */
def newConstructor(cls: ClassSymbol, flags: FlagSet, paramNames: List[TermName], paramTypes: List[Type], privateWithin: Symbol = NoSymbol, coord: Coord = NoCoord) =
newSymbol(cls, nme.CONSTRUCTOR, flags | Method, MethodType(paramNames, paramTypes)(_ => cls.typeConstructor), privateWithin, coord)
+ /** Create an empty default constructor symbol for given class `cls`. */
def newDefaultConstructor(cls: ClassSymbol) =
newConstructor(cls, EmptyFlags, Nil, Nil)
+ /** Create a symbol representing a selftype declaration for class `cls`. */
def newSelfSym(cls: ClassSymbol) =
- ctx.newSymbol(cls, nme.THIS, SyntheticArtifact, cls.selfType)
+ ctx.newSymbol(cls, nme.THIS, SyntheticArtifact, cls.classInfo.selfType)
/** Create new type parameters with given owner, names, and flags.
* @param boundsFn A function that, given type refs to the newly created
@@ -133,12 +212,11 @@ trait Symbols { this: Context =>
names: List[TypeName],
flags: FlagSet,
boundsFn: List[TypeRef] => List[Type]) = {
- lazy val tparams: List[TypeSymbol] = names map { name =>
- newLazySymbol(owner, name, flags | TypeParam, { denot =>
- denot.info = bounds(denot.symbol.asType)
- })
+ val tparams = names map (_ => newNakedSymbol[TypeName](NoCoord))
+ val bounds = boundsFn(tparams map (_.symbolicRef))
+ (names, tparams, bounds).zipped foreach { (name, tparam, bound) =>
+ tparam.denot = SymDenotation(tparam, owner, name, flags, bound)
}
- lazy val bounds = (tparams zip boundsFn(tparams map (_.typeConstructor))).toMap
tparams
}
@@ -148,38 +226,30 @@ trait Symbols { this: Context =>
* references are brought over from originals to copies.
* Do not copy any symbols if all their attributes stay the same.
*/
- def mapSymbols(originals: List[Symbol], typeMap: TypeMap = IdentityTypeMap, ownerMap: OwnerMap = identity) = {
+ def mapSymbols(
+ originals: List[Symbol],
+ typeMap: TypeMap = IdentityTypeMap,
+ ownerMap: OwnerMap = identity)
+ =
if (originals forall (sym =>
- sym.isInvariantUnder(typeMap) && ownerMap(sym.owner) == sym.owner))
+ (typeMap(sym.info) eq sym.info) && (ownerMap(sym.owner) eq sym.owner)))
originals
else {
- lazy val copies: List[Symbol] = originals map { orig =>
- if (orig.isClass)
- newLazyClassSymbol(ownerMap(orig.owner), orig.asClass.name, orig.flags, copyClassCompleter, orig.asClass.associatedFile, orig.coord)
- else
- newLazySymbol(ownerMap(orig.owner), orig.name, orig.flags, copySymCompleter, orig.coord)
- }
- lazy val prev = (copies zip originals).toMap
- lazy val copyTypeMap = typeMap andThen ((tp: Type) => tp.substSym(originals, copies))
- lazy val mapper = new TypedTrees.TreeMapper(typeMap, ownerMap)
- def mapAnnotations(denot: isLazy[_]): Unit = {
- denot.annotations = denot.annotations.mapConserve(mapper.apply)
- denot.privateWithin = ownerMap(denot.privateWithin)
- }
- def copySymCompleter(denot: LazySymDenotation): Unit = {
- denot.info = copyTypeMap(prev(denot.symbol).info)
- mapAnnotations(denot)
- }
- def copyClassCompleter(denot: LazyClassDenotation): Unit = {
- denot.parents = prev(denot.symbol).asClass.parents mapConserve (
- tp => copyTypeMap(tp).asInstanceOf[TypeRef])
- denot.selfType = copyTypeMap(prev(denot.symbol).asClass.selfType)
- denot.decls = copyTypeMap.mapOver(prev(denot.symbol).asClass.decls)
- mapAnnotations(denot)
+ val copies: List[Symbol] = for (original <- originals) yield
+ newNakedSymbol[original.ThisName](original.coord)
+ val copyTypeMap = typeMap andThen ((tp: Type) => tp.substSym(originals, copies))
+ val copyTreeMap = new TypedTrees.TreeMapper(copyTypeMap, ownerMap)
+ (originals, copies).zipped foreach {(original, copy) =>
+ val odenot = original.denot
+ copy.denot = odenot.copySymDenotation(
+ symbol = copy,
+ owner = ownerMap(odenot.owner),
+ info = copyTypeMap(odenot.info),
+ privateWithin = ownerMap(odenot.privateWithin),
+ annotations = odenot.annotations.mapConserve(copyTreeMap.apply))
}
copies
}
- }
// ----- Locating predefined symbols ----------------------------------------
@@ -197,7 +267,7 @@ object Symbols {
/** A Symbol represents a Scala definition/declaration or a package.
*/
- class Symbol(val coord: Coord, denotf: Symbol => SymDenotation) extends DotClass {
+ class Symbol private[Symbols] (val coord: Coord) extends DotClass {
type ThisName <: Name
@@ -219,7 +289,11 @@ object Symbols {
}
/** The last denotation of this symbol */
- private[this] var lastDenot: SymDenotation = denotf(this)
+ private[this] var lastDenot: SymDenotation = _
+
+ /** Set the denotation of this symbol */
+ private[Symbols] def denot_=(d: SymDenotation) =
+ lastDenot = d
/** The current denotation of this symbol */
final def denot(implicit ctx: Context): SymDenotation = {
@@ -257,7 +331,9 @@ object Symbols {
/** The current name of this symbol */
final def name(implicit ctx: Context): ThisName = denot.name.asInstanceOf[ThisName]
- /** The source or class file from which this class was generated, null if not applicable. */
+ /** The source or class file from which this class or
+ * the class containing this symbol was generated, null if not applicable.
+ */
def associatedFile(implicit ctx: Context): AbstractFile =
this.denot.topLevelClass.symbol.associatedFile
@@ -289,7 +365,8 @@ object Symbols {
type TermSymbol = Symbol { type ThisName = TermName }
type TypeSymbol = Symbol { type ThisName = TypeName }
- class ClassSymbol(coord: Coord, denotf: ClassSymbol => ClassDenotation, assocFile: AbstractFile) extends Symbol(coord, s => denotf(s.asClass)) {
+ class ClassSymbol private[Symbols] (coord: Coord, assocFile: AbstractFile)
+ extends Symbol(coord) {
type ThisName = TypeName
@@ -324,12 +401,14 @@ object Symbols {
}
}
- class ErrorSymbol(val underlying: Symbol, msg: => String)(implicit ctx: Context) extends Symbol(NoCoord, sym => underlying.denot) {
+ class ErrorSymbol(val underlying: Symbol, msg: => String)(implicit ctx: Context) extends Symbol(NoCoord) {
type ThisName = underlying.ThisName
+ denot = underlying.denot
}
- object NoSymbol extends Symbol(NoCoord, sym => NoDenotation) {
+ object NoSymbol extends Symbol(NoCoord) {
override def exists = false
+ denot = NoDenotation
}
implicit class Copier[N <: Name](sym: Symbol { type ThisName = N })(implicit ctx: Context) {
@@ -338,37 +417,19 @@ object Symbols {
owner: Symbol = sym.owner,
name: N = sym.name,
flags: FlagSet = sym.flags,
- privateWithin: Symbol = sym.privateWithin,
info: Type = sym.info,
- coord: Coord = sym.coord): Symbol =
- if (sym.isClass) {
- assert(info eq sym.info)
- new ClassCopier(sym.asClass).copy(owner, name.asTypeName, flags, privateWithin = privateWithin, coord = coord)
- } else
- ctx.newSymbol(owner, name, flags, info, privateWithin, sym.coord)
- }
-
- implicit class ClassCopier(cls: ClassSymbol)(implicit ctx: Context) {
- /** Copy a class symbol, overriding selective fields */
- def copy(
- owner: Symbol = cls.owner,
- name: TypeName = cls.name.asTypeName,
- flags: FlagSet = cls.flags,
- parents: List[TypeRef] = cls.classDenot.parents,
- privateWithin: Symbol = cls.privateWithin,
- selfType: Type = cls.selfType,
- decls: Scope = cls.decls,
- associatedFile: AbstractFile = cls.associatedFile,
- coord: Coord = cls.coord) =
- ctx.newClassSymbol(owner, name, flags, parents, privateWithin, selfType, decls, associatedFile, coord)
+ privateWithin: Symbol = sym.privateWithin,
+ coord: Coord = sym.coord,
+ associatedFile: AbstractFile = sym.associatedFile): Symbol =
+ if (sym.isClass)
+ ctx.newClassSymbol(owner, name.asTypeName, flags, _ => info, privateWithin, coord, associatedFile)
+ else
+ ctx.newSymbol(owner, name, flags, info, privateWithin, coord)
}
implicit def defn(implicit ctx: Context): Definitions = ctx.definitions
- implicit def toFlagSet(sym: Symbol)(implicit ctx: Context): FlagSet = sym.flags
-
implicit def toDenot(sym: Symbol)(implicit ctx: Context): SymDenotation = sym.denot
implicit def toClassDenot(cls: ClassSymbol)(implicit ctx: Context): ClassDenotation = cls.classDenot
-
}
diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala
index 71bc9f801..e7377ce18 100644
--- a/src/dotty/tools/dotc/core/TypeOps.scala
+++ b/src/dotty/tools/dotc/core/TypeOps.scala
@@ -192,7 +192,7 @@ trait TypeOps { this: Context =>
/** Normalize a list of parent types of class `cls` that may contain refinements
* to a list of typerefs, by converting all refinements to member
- * definitions in scope `decls`.
+ * definitions in scope `decls`. Can add members to `decls` as a side-effect.
*/
def normalizeToRefs(parents: List[Type], cls: ClassSymbol, decls: Scope): List[TypeRef] = {
var refinements = Map[TypeName, Type]()
diff --git a/src/dotty/tools/dotc/core/TypedTrees.scala b/src/dotty/tools/dotc/core/TypedTrees.scala
index 42eb166ff..49d062330 100644
--- a/src/dotty/tools/dotc/core/TypedTrees.scala
+++ b/src/dotty/tools/dotc/core/TypedTrees.scala
@@ -250,8 +250,8 @@ object TypedTrees {
def ClassDef(cls: ClassSymbol, typeParams: List[TypeSymbol], body: List[Tree])(implicit ctx: Context): ClassDef = {
val parents = cls.info.parents map (TypeTree(_))
val selfType =
- if (cls.selfType eq cls.typeConstructor) EmptyValDef
- else ValDef(ctx.newSelfSym(cls))
+ if (cls.classInfo.optSelfType.exists) ValDef(ctx.newSelfSym(cls))
+ else EmptyValDef
def isOwnTypeParamAccessor(stat: Tree) =
(stat.symbol is TypeParam) && stat.symbol.owner == cls
val (tparamAccessors, rest) = body partition isOwnTypeParamAccessor
@@ -466,8 +466,8 @@ object TypedTrees {
case _ => true
}
def noLeaksInClass(sym: ClassSymbol): Boolean =
- (sym.parents forall noLeaksIn) &&
- (sym.decls.toList forall (t => noLeaksIn(t.info)))
+ (sym.classInfo.parents forall noLeaksIn) &&
+ (sym.classInfo.decls.toList forall (t => noLeaksIn(t.info)))
check(noLeaksIn(tree.tpe))
case If(cond, thenp, elsep) =>
check(cond.isValue); check(thenp.isValue); check(elsep.isValue)
@@ -658,8 +658,7 @@ object TypedTrees {
else
new TreeMapper(
typeMap andThen ((tp: Type) => tp.substSym(locals, mapped)),
- ownerMap andThen (locals zip mapped).toMap)
- .transform(trees, c)
+ ownerMap andThen (locals zip mapped).toMap).transform(trees, c)
}
def apply[ThisTree <: tpd.Tree](tree: ThisTree): ThisTree = transform(tree, ()).asInstanceOf[ThisTree]
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 09a2585d0..292f78d8e 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -63,7 +63,7 @@ object Types {
/** The type symbol associated with the type */
final def typeSymbol(implicit ctx: Context): Symbol = this match {
case tp: TypeRef => tp.symbol
- case tp: ClassInfo => tp.classd.symbol
+ case tp: ClassInfo => tp.cls
case tp: TypeProxy => tp.underlying.typeSymbol
case _ => NoSymbol
}
@@ -124,7 +124,7 @@ object Types {
*/
final def memberNames(pre: Type, keepOnly: NameFilter)(implicit ctx: Context): Set[Name] = this match {
case tp: ClassInfo =>
- tp.classd.memberNames(keepOnly) filter (keepOnly(pre, _))
+ tp.cls.memberNames(keepOnly) filter (keepOnly(pre, _))
case tp: RefinedType =>
var ns = tp.parent.memberNames(pre, keepOnly)
if (keepOnly(pre, tp.name)) ns += tp.name
@@ -319,7 +319,7 @@ object Types {
*/
final def decls(implicit ctx: Context): Scope = this match {
case tp: ClassInfo =>
- tp.classd.decls
+ tp.decls
case tp: TypeProxy =>
tp.underlying.decls
case _ =>
@@ -337,11 +337,11 @@ object Types {
/** The non-private class member declaration of this type with given name */
final def findDecl(name: Name, pre: Type, excluded: FlagSet)(implicit ctx: Context): Denotation = this match {
case tp: ClassInfo =>
- tp.classd.decls
+ tp.decls
.denotsNamed(name)
.filterAccessibleFrom(pre)
.filterExcluded(excluded)
- .asSeenFrom(pre, tp.classd.symbol)
+ .asSeenFrom(pre, tp.cls)
.toDenot
case tp: TypeProxy =>
tp.underlying.findDecl(name, pre, excluded)
@@ -370,12 +370,12 @@ object Types {
case tp: TypeProxy =>
tp.underlying.findMember(name, pre, excluded)
case tp: ClassInfo =>
- val classd = tp.classd
- val candidates = classd.membersNamed(name)
+ val cls = tp.cls
+ val candidates = cls.membersNamed(name)
val results = candidates
.filterAccessibleFrom(pre)
.filterExcluded(excluded)
- .asSeenFrom(pre, classd.symbol)
+ .asSeenFrom(pre, cls)
if (results.exists) results.toDenot
else new ErrorDenotation // todo: refine
case tp: AndType =>
@@ -454,7 +454,7 @@ object Types {
case tp: TypeProxy =>
tp.underlying.baseClasses
case tp: ClassInfo =>
- tp.classd.baseClasses
+ tp.cls.baseClasses
case _ => Nil
}
@@ -484,7 +484,7 @@ object Types {
*/
final def typeParams(implicit ctx: Context): List[TypeSymbol] = this match {
case tp: ClassInfo =>
- tp.classd.typeParams
+ tp.cls.typeParams
case tp: TypeProxy =>
tp.underlying.typeParams
case _ => Nil
@@ -806,7 +806,7 @@ object Types {
// --- Other SingletonTypes: ThisType/SuperType/ConstantType ---------------------------
abstract case class ThisType(cls: ClassSymbol) extends CachedProxyType with SingletonType {
- override def underlying(implicit ctx: Context) = cls.selfType
+ override def underlying(implicit ctx: Context) = cls.classInfo.selfType
override def computeHash = doHash(cls)
}
@@ -1075,31 +1075,49 @@ object Types {
// ------ ClassInfo, Type Bounds ------------------------------------------------------------
- abstract case class ClassInfo(prefix: Type, classd: ClassDenotation) extends CachedGroundType with TypeType {
+ /** The info of a class during a period.
+ * @param pre The prefix on which all class attributes need to be rebased.
+ * @param cls The class symbol.
+ * @param classParents The parent types of this class.
+ * These are all normalized to be TypeRefs by moving any refinements
+ * to be member definitions of the class itself.
+ * @param decls The symbols defined directly in this class.
+ * @param optSelfType The type of `this` in this class, if explicitly given, NoType otherwise.
+ */
+ abstract case class ClassInfo(
+ prefix: Type,
+ cls: ClassSymbol,
+ classParents: List[TypeRef],
+ decls: Scope,
+ optSelfType: Type) extends CachedGroundType with TypeType {
+
+ def selfType(implicit ctx: Context): Type =
+ if (optSelfType.exists) optSelfType else cls.typeConstructor
-/* def typeTemplate(implicit ctx: Context): Type =
- classd.typeTemplate asSeenFrom (prefix, classd.symbol)
-*/
def typeConstructor(implicit ctx: Context): Type =
- NamedType(prefix, classd.symbol.name)
+ NamedType(prefix, cls.name)
// cached because baseType needs parents
private var parentsCache: List[TypeRef] = null
+ def rebase(tp: Type)(implicit ctx: Context): Type =
+ tp.substThis(cls, prefix)
+
override def parents(implicit ctx: Context): List[TypeRef] = {
if (parentsCache == null)
- parentsCache = classd.parents.mapConserve(_.substThis(classd.symbol, prefix).asInstanceOf[TypeRef])
+ parentsCache = classParents.mapConserve(rebase(_).asInstanceOf[TypeRef])
parentsCache
}
- override def computeHash = doHash(classd.symbol, prefix)
+ override def computeHash = doHash(cls, prefix)
}
- final class CachedClassInfo(prefix: Type, classd: ClassDenotation) extends ClassInfo(prefix, classd)
+ final class CachedClassInfo(prefix: Type, cls: ClassSymbol, classParents: List[TypeRef], decls: Scope, optSelfType: Type)
+ extends ClassInfo(prefix, cls, classParents, decls, optSelfType)
object ClassInfo {
- def apply(prefix: Type, classd: ClassDenotation)(implicit ctx: Context) =
- unique(new CachedClassInfo(prefix, classd))
+ def apply(prefix: Type, cls: ClassSymbol, classParents: List[TypeRef], decls: Scope, optSelfType: Type = NoType)(implicit ctx: Context) =
+ unique(new CachedClassInfo(prefix, cls, classParents, decls, optSelfType))
}
abstract case class TypeBounds(lo: Type, hi: Type) extends CachedProxyType with TypeType {
diff --git a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
index 2f370fbdd..3a1e81e2d 100644
--- a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
+++ b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
@@ -15,11 +15,10 @@ import io.AbstractFile
class ClassfileParser(
classfile: AbstractFile,
- classRoot: LazyClassDenotation,
- moduleRoot: LazyClassDenotation)(implicit cctx: CondensedContext) {
+ classRoot: ClassDenotation,
+ moduleRoot: ClassDenotation)(implicit cctx: CondensedContext) {
import ClassfileConstants._
- import cctx.debuglog
import cctx.base.{settings, loaders, definitions => defn}
protected val in = new AbstractFileReader(classfile)
@@ -43,7 +42,7 @@ class ClassfileParser(
}
def run(): Unit = try {
- debuglog("[class] >> " + classRoot.fullName)
+ cctx.debuglog("[class] >> " + classRoot.fullName)
parseHeader
this.pool = new ConstantPool
parseClass()
@@ -128,8 +127,8 @@ class ClassfileParser(
instanceScope enter cctx.newDefaultConstructor(classRoot.symbol.asClass)
classInfo = parseAttributes(classRoot.symbol, classInfo)
- assignClassFields(classRoot, classInfo, classRoot.typeConstructor)
- assignClassFields(moduleRoot, staticInfo, moduleRoot.typeConstructor)
+ setClassInfo(classRoot, classInfo)
+ setClassInfo(moduleRoot, staticInfo)
}
/** Add type parameters of enclosing classes */
@@ -151,42 +150,45 @@ class ClassfileParser(
else FlagTranslation.fieldFlags(jflags)
val name = pool.getName(in.nextChar)
if (!(sflags is Flags.Private) || name == nme.CONSTRUCTOR || settings.optimise.value)
- cctx.newLazySymbol(getOwner(jflags), name, sflags, memberCompleter, start).entered
+ cctx.newSymbol(
+ getOwner(jflags), name, sflags, memberCompleter, coord = start).entered
}
- val memberCompleter: SymCompleter = { denot =>
- val oldbp = in.bp
- try {
- in.bp = denot.symbol.coord.toIndex
- val sym = denot.symbol
- val jflags = in.nextChar
- val isEnum = (jflags & JAVA_ACC_ENUM) != 0
- val name = pool.getName(in.nextChar)
- val info = pool.getType(in.nextChar)
-
- denot.info = if (isEnum) ConstantType(Constant(sym)) else info
- if (name == nme.CONSTRUCTOR)
- // if this is a non-static inner class, remove the explicit outer parameter
- innerClasses.get(currentClassName) match {
- case Some(entry) if !isStatic(entry.jflags) =>
- val mt @ MethodType(paramnames, paramtypes) = info
- denot.info = mt.derivedMethodType(paramnames.tail, paramtypes.tail, mt.resultType)
+ val memberCompleter = new LazyType {
+ def complete(denot: SymDenotation): Unit = {
+ val oldbp = in.bp
+ try {
+ in.bp = denot.symbol.coord.toIndex
+ val sym = denot.symbol
+ val jflags = in.nextChar
+ val isEnum = (jflags & JAVA_ACC_ENUM) != 0
+ val name = pool.getName(in.nextChar)
+ val info = pool.getType(in.nextChar)
+
+ denot.info = if (isEnum) ConstantType(Constant(sym)) else info
+ if (name == nme.CONSTRUCTOR)
+ // if this is a non-static inner class, remove the explicit outer parameter
+ innerClasses.get(currentClassName) match {
+ case Some(entry) if !isStatic(entry.jflags) =>
+ val mt @ MethodType(paramnames, paramtypes) = info
+ denot.info = mt.derivedMethodType(paramnames.tail, paramtypes.tail, mt.resultType)
- }
- setPrivateWithin(denot, jflags)
- denot.info = parseAttributes(sym, info)
+ }
+ setPrivateWithin(denot, jflags)
+ denot.info = parseAttributes(sym, info)
- if ((denot is Flags.Method) && (jflags & JAVA_ACC_VARARGS) != 0)
- denot.info = arrayToRepeated(denot.info)
+ if ((denot is Flags.Method) && (jflags & JAVA_ACC_VARARGS) != 0)
+ denot.info = arrayToRepeated(denot.info)
- // seal java enums
- if (isEnum) {
- val enumClass = sym.owner.linkedClass
- if (!(enumClass is Flags.Sealed)) enumClass.setFlag(Flags.AbstractSealed)
- enumClass.addAnnotation(Annotation.makeChild(sym))
+ // seal java enums
+ if (isEnum) {
+ val enumClass = sym.owner.linkedClass
+ if (!(enumClass is Flags.Sealed)) enumClass.setFlag(Flags.AbstractSealed)
+ enumClass.addAnnotation(Annotation.makeChild(sym))
+ }
+ } finally {
+ in.bp = oldbp
}
- } finally {
- in.bp = oldbp
}
}
@@ -309,13 +311,15 @@ class ClassfileParser(
var tparams = classTParams
- def typeParamCompleter(start: Int): SymCompleter = { denot =>
- val savedIndex = index
- try {
- index = start
- denot.info = sig2typeBounds(tparams, skiptvs = false)
- } finally {
- index = savedIndex
+ def typeParamCompleter(start: Int) = new LazyType {
+ def complete(denot: SymDenotation): Unit = {
+ val savedIndex = index
+ try {
+ index = start
+ denot.info = sig2typeBounds(tparams, skiptvs = false)
+ } finally {
+ index = savedIndex
+ }
}
}
@@ -326,8 +330,8 @@ class ClassfileParser(
val start = index
while (sig(index) != '>') {
val tpname = subName(':'.==).toTypeName
- val s = cctx.newLazySymbol(
- owner, tpname, Flags.TypeParam, typeParamCompleter(index), indexCoord(index))
+ val s = cctx.newSymbol(
+ owner, tpname, Flags.TypeParam, typeParamCompleter(index), coord = indexCoord(index))
tparams = tparams + (tpname -> s)
sig2typeBounds(tparams, skiptvs = true)
newTParams += s
@@ -506,7 +510,7 @@ class ClassfileParser(
loaders.enterClassAndModule(
getOwner(jflags),
entry.originalName,
- new ClassfileLoader(file)(cctx),
+ new ClassfileLoader(file),
FlagTranslation.classFlags(jflags))
for (entry <- innerClasses.values) {
@@ -702,7 +706,7 @@ class ClassfileParser(
protected def getScope(flags: Int): Scope =
if (isStatic(flags)) staticScope else instanceScope
- private def setPrivateWithin(denot: isLazy[_], jflags: Int) {
+ private def setPrivateWithin(denot: SymDenotation, jflags: Int) {
if ((jflags & (JAVA_ACC_PRIVATE | JAVA_ACC_PUBLIC)) == 0)
// See ticket #1687 for an example of when topLevelClass is NoSymbol: it
// apparently occurs when processing v45.3 bytecode.
diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
index 35ef5dece..c8001f05d 100644
--- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
@@ -52,16 +52,15 @@ object UnPickler {
tp.derivedPolyType(paramNames, tp.paramBounds, arrayToRepeated(tp.resultType))
}
- def assignClassFields(denot: LazyClassDenotation, info: Type, selfType: Type)(implicit ctx: Context): Unit = {
- val cls = denot.symbol
+ def setClassInfo(denot: ClassDenotation, info: Type, optSelfType: Type = NoType)(implicit ctx: Context): Unit = {
+ val cls = denot.classSymbol
val (tparams, TempClassInfoType(parents, decls, clazz)) = info match {
case TempPolyType(tps, cinfo) => (tps, cinfo)
case cinfo => (Nil, cinfo)
}
+ val parentRefs = ctx.normalizeToRefs(parents, cls, decls)
tparams foreach decls.enter
- denot.parents = ctx.normalizeToRefs(parents, cls, decls)
- denot.selfType = selfType
- denot.decls = decls
+ denot.info = ClassInfo(denot.owner.thisType, denot.classSymbol, parentRefs, decls, optSelfType)
}
}
@@ -72,7 +71,7 @@ object UnPickler {
* @param moduleroot the top-level module class which is unpickled, or NoSymbol if inapplicable
* @param filename filename associated with bytearray, only used for error messages
*/
-class UnPickler(bytes: Array[Byte], classRoot: LazyClassDenotation, moduleRoot: LazyClassDenotation)(implicit cctx: CondensedContext)
+class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleRoot: ClassDenotation)(implicit cctx: CondensedContext)
extends PickleBuffer(bytes, 0, -1) {
import UnPickler._
@@ -347,8 +346,8 @@ class UnPickler(bytes: Array[Byte], classRoot: LazyClassDenotation, moduleRoot:
def isClassRoot = (name == classRoot.name) && (owner == classRoot.owner)
def isModuleRoot = (name.toTermName == moduleRoot.name.toTermName) && (owner == moduleRoot.owner)
- def completeRoot(denot: LazyClassDenotation): Symbol = {
- atReadPos(start.toIndex, () => completeLocal(denot))
+ def completeRoot(denot: ClassDenotation): Symbol = {
+ atReadPos(start.toIndex, () => localUnpickler.parseToCompletion(denot))
denot.symbol
}
@@ -369,23 +368,23 @@ class UnPickler(bytes: Array[Byte], classRoot: LazyClassDenotation, moduleRoot:
name1 = name1.expandedName(owner)
flags1 |= TypeParamFlags
}
- cctx.newLazySymbol(owner, name1, flags1, symUnpickler, coord = start)
+ cctx.newSymbol(owner, name1, flags1, localUnpickler, coord = start)
case CLASSsym =>
if (isClassRoot) completeRoot(classRoot)
else if (isModuleRoot) completeRoot(moduleRoot)
- else cctx.newLazyClassSymbol(owner, name.asTypeName, flags, classUnpickler, coord = start)
+ else cctx.newClassSymbol(owner, name.asTypeName, flags, localUnpickler, coord = start)
case MODULEsym | VALsym =>
if (isModuleRoot) {
moduleRoot.flags = flags
moduleRoot.symbol
- } else cctx.newLazySymbol(owner, name.asTermName, flags, symUnpickler, coord = start)
+ } else cctx.newSymbol(owner, name.asTermName, flags, localUnpickler, coord = start)
case _ =>
errorBadSignature("bad symbol tag: " + tag)
})
}
- def completeLocal[D <: SymDenotation](denot: isLazy[D]): Unit = {
- def parseToCompletion() = {
+ val localUnpickler = new LazyType {
+ def parseToCompletion(denot: SymDenotation) = {
val tag = readByte()
val end = readNat() + readIndex
def atEnd = readIndex == end
@@ -402,7 +401,10 @@ class UnPickler(bytes: Array[Byte], classRoot: LazyClassDenotation, moduleRoot:
}
val tp = at(inforef, () => readType(forceProperType = denot.isTerm))
denot match {
- case denot: LazySymDenotation =>
+ case denot: ClassDenotation =>
+ val optSelfType = if (atEnd) NoType else readTypeRef()
+ setClassInfo(denot, tp, optSelfType)
+ case denot =>
denot.info = if (tag == ALIASsym) TypeAlias(tp) else depoly(tp)
if (atEnd) {
assert(!(denot is SuperAccessor), denot)
@@ -414,17 +416,13 @@ class UnPickler(bytes: Array[Byte], classRoot: LazyClassDenotation, moduleRoot:
val alias = at(aliasRef, readDisambiguatedSymbol(disambiguate)).asTerm
denot.addAnnotation(Annotation.makeAlias(alias))
}
- case denot: LazyClassDenotation =>
- val selfType = if (atEnd) denot.typeConstructor else readTypeRef()
- assignClassFields(denot, tp, selfType)
}
}
- atReadPos(denot.symbol.coord.toIndex, parseToCompletion)
+ def complete(denot: SymDenotation): Unit = {
+ atReadPos(denot.symbol.coord.toIndex, () => parseToCompletion(denot))
+ }
}
- val symUnpickler: SymCompleter = completeLocal
- val classUnpickler: ClassCompleter = completeLocal
-
/** Convert
* tp { type name = sym } forSome { sym >: L <: H }
* to