From 36b9128d2214a927d642e87da3322b4ed4e76c58 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 24 Feb 2013 18:42:17 +0100 Subject: 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. --- src/dotty/tools/dotc/config/JavaPlatform.scala | 4 +- src/dotty/tools/dotc/config/Platform.scala | 5 +- src/dotty/tools/dotc/core/Contexts.scala | 5 +- src/dotty/tools/dotc/core/Definitions.scala | 22 +- src/dotty/tools/dotc/core/Denotations.scala | 2 +- src/dotty/tools/dotc/core/Flags.scala | 5 +- src/dotty/tools/dotc/core/Printers.scala | 12 +- src/dotty/tools/dotc/core/SymDenotations.scala | 508 +++++++++------------ src/dotty/tools/dotc/core/SymbolLoaders.scala | 57 ++- src/dotty/tools/dotc/core/Symbols.scala | 317 +++++++------ src/dotty/tools/dotc/core/TypeOps.scala | 2 +- src/dotty/tools/dotc/core/TypedTrees.scala | 11 +- src/dotty/tools/dotc/core/Types.scala | 60 ++- .../tools/dotc/core/pickling/ClassfileParser.scala | 98 ++-- src/dotty/tools/dotc/core/pickling/UnPickler.scala | 40 +- 15 files changed, 582 insertions(+), 566 deletions(-) (limited to 'src/dotty/tools') 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(???, "") /** Denotation is in train of being loaded and completed, flag to catch cyclic dependencies */ - final val Locked = commonFlag(???, "") + final val CompletionStarted = commonFlag(???, "") /** Variable is accessed from nested function. */ final val Captured = termFlag(???, "") @@ -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, "".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 = "".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 -- cgit v1.2.3