diff options
Diffstat (limited to 'src/dotty/tools/dotc')
-rw-r--r-- | src/dotty/tools/dotc/core/Contexts.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/SymDenotations.scala | 31 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/SymbolLoaders.scala | 67 |
3 files changed, 44 insertions, 56 deletions
diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala index 8edbec847..6a674dba8 100644 --- a/src/dotty/tools/dotc/core/Contexts.scala +++ b/src/dotty/tools/dotc/core/Contexts.scala @@ -64,8 +64,10 @@ object Contexts { def enclClass: Context = ??? def erasedTypes: Boolean = ??? def debug: Boolean = ??? + def error(msg: String) = ??? def warning(msg: String) = ??? def inform(msg: String) = ??? + def informTime(msg: String, start: Long): Unit = ??? def fresh: FreshContext = { val newctx = super.clone.asInstanceOf[FreshContext] diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index b8fc49a45..f103e14d4 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -27,9 +27,10 @@ object SymDenotations { def info: Type - // The following 4 members are overridden is instances of isLazy + // The following 5 members are overridden by instances of isLazy def isLoaded = true def isCompleted = true + def exists(implicit ctx: Context) = true protected[core] def tryLoad(): Unit = unsupported("tryLoad") protected[core] def tryComplete(): Unit = unsupported("tryComplete") @@ -622,6 +623,9 @@ object SymDenotations { 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 } @@ -663,6 +667,8 @@ object SymDenotations { def selfType: Type = { if (_selfType == null) tryComplete(); _selfType } final def decls: Scope = { if (_decls == null) tryComplete(); _decls } final def preCompleteDecls = { if (_decls == null) tryLoad(); _decls } + + final override def exists(implicit ctx: Context) = { ensureCompleted(); _parents != null } } object NoDenotation extends SymDenotation(EmptyFlags) { @@ -692,12 +698,19 @@ object SymDenotations { flags &~= Locked } - override protected[core] def tryComplete(): Unit = { - val c = completer - completer = null - if (c == null) throw new CyclicReference(symbol) - c.complete(this) - } + override protected[core] def tryComplete(): Unit = + try { + if (flags is Locked) throw new CyclicReference(symbol) + setFlags(Locked) + val c = completer + completer = null // set completer to null to avoid space leaks + // and to make any subsequent completion attempt a CompletionError + c.complete(this) + } catch { + case _: NullPointerException => throw new CompletionError(this) + } finally { + flags &~= Locked + } private[this] var _privateWithin: Symbol = _ def privateWithin: Symbol = { if (_privateWithin == null) tryLoad(); _privateWithin } @@ -718,7 +731,7 @@ object SymDenotations { type ClassCompleter = Completer[LazyClassDenotation] class ModuleCompleter(cctx: CondensedContext) extends Completer[LazySymDenotation] { - implicit val ctx: Context = cctx + implicit def ctx: Context = cctx def classDenot(denot: LazySymDenotation) = denot.moduleClass.denot.asInstanceOf[LazyClassDenotation] def copyLoadedFields(denot: LazySymDenotation, from: LazyClassDenotation) = { @@ -735,6 +748,8 @@ object SymDenotations { copyCompletedFields(denot, classDenot(denot)) } + class CompletionError(denot: SymDenotation) extends Error("Trying to access missing symbol ${denot.symbol.fullName}") + // ---- Name filter -------------------------------------------------------- object NameFilter { diff --git a/src/dotty/tools/dotc/core/SymbolLoaders.scala b/src/dotty/tools/dotc/core/SymbolLoaders.scala index 6aa959887..671c4ea65 100644 --- a/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -14,9 +14,8 @@ import Contexts._, Symbols._, Flags._, SymDenotations._, Types._ import Decorators.StringDecorator //import classfile.ClassfileParser -abstract class SymbolLoader extends ClassCompleter - +/** A base class for Symbol loaders with some overridable behavior */ class SymbolLoaders { protected def enterIfNew(owner: Symbol, member: Symbol, completer: SymbolLoader)(implicit ctx: Context): Symbol = { @@ -28,14 +27,14 @@ class SymbolLoaders { /** Enter class with given `name` into scope of `owner`. */ def enterClass(owner: Symbol, name: String, completer: SymbolLoader)(implicit ctx: Context): Symbol = { - val cls = ctx.newLazyClassSymbol(owner, name.toTypeName, EmptyFlags, completer) + val cls = ctx.newLazyClassSymbol(owner, name.toTypeName, EmptyFlags, completer, assocFile = completer.sourceFileOrNull) enterIfNew(owner, cls, completer) } /** Enter module with given `name` into scope of `owner`. */ def enterModule(owner: Symbol, name: String, completer: SymbolLoader)(implicit ctx: Context): Symbol = { - val module = ctx.newLazyModuleSymbol(owner, name.toTermName, EmptyFlags, completer) + val module = ctx.newLazyModuleSymbol(owner, name.toTermName, EmptyFlags, completer, assocFile = completer.sourceFileOrNull) enterIfNew(owner, module, completer) } @@ -119,20 +118,20 @@ class SymbolLoaders { def needCompile(bin: AbstractFile, src: AbstractFile) = src.lastModified >= bin.lastModified -}/* +} /** * A lazy type that completes itself by calling parameter doComplete. * Any linked modules/classes or module classes are also initialized. * Todo: consider factoring out behavior from TopClassCompleter/SymbolLoader into * supertrait SymLoader */ - abstract class SymbolLoader extends ClassCompleter { + abstract class SymbolLoader(cctx: CondensedContext) extends ClassCompleter { + implicit def ctx: Context = cctx /** Load source or class file for `root`, return */ - protected def doComplete(root: Symbol): Unit - - def sourcefile: Option[AbstractFile] = None + protected def doComplete(root: LazyClassDenotation): Unit + def sourceFileOrNull: AbstractFile = null /** * Description of the resource (ClassPath, AbstractFile, MsilFile) * being processed by this loader @@ -141,62 +140,34 @@ class SymbolLoaders { private var ok = false - private def setSource(sym: Symbol) { - sourcefile foreach (sf => sym match { - case cls: ClassSymbol => cls.sourceFile = sf - case mod: ModuleSymbol => mod.moduleClass.sourceFile = sf - case _ => () - }) - } - - override def complete(root: Symbol) { + override def complete(root: LazyClassDenotation) { def signalError(ex: Exception) { ok = false - if (settings.debug.value) ex.printStackTrace() + if (ctx.settings.debug.value) ex.printStackTrace() val msg = ex.getMessage() - // SI-5593 Scaladoc's current strategy is to visit all packages in search of user code that can be documented - // therefore, it will rummage through the classpath triggering errors whenever it encounters package objects - // that are not in their correct place (see bug for details) - if (!settings.isScaladoc) - globalError( - if (msg eq null) "i/o error while loading " + root.name - else "error while loading " + root.name + ", " + msg); + ctx.error( + if (msg eq null) "i/o error while loading " + root.name + else "error while loading " + root.name + ", " + msg); } try { val start = currentTime - val currentphase = phase doComplete(root) - phase = currentphase - informTime("loaded " + description, start) + ctx.informTime("loaded " + description, start) ok = true - setSource(root) - setSource(root.companionSymbol) // module -> class, class -> module } catch { case ex: IOException => signalError(ex) case ex: MissingRequirementError => signalError(ex) } - initRoot(root) - if (!root.isPackageClass) initRoot(root.companionSymbol) - } - - override def load(root: Symbol) { complete(root) } - - private def markAbsent(sym: Symbol): Unit = { - val tpe: Type = if (ok) NoType else ErrorType - - if (sym != NoSymbol) - sym setInfo tpe - } - private def initRoot(root: Symbol) { - if (root.rawInfo == this) - List(root, root.moduleClass) foreach markAbsent - else if (root.isClass && !root.isModuleClass) - root.rawInfo.load(root) + root.linkedClass.denot match { + case companion: LazyClassDenotation => companion.completer = null + } } } + /* + /** * Load contents of a package */ |