From f4e9a881a561e28900becc7deea520b43e57fb31 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 9 Feb 2014 13:35:17 +0100 Subject: WIP: Fixes to bring symbols forward --- src/dotty/tools/dotc/core/Denotations.scala | 27 +++++++++------- src/dotty/tools/dotc/core/SymDenotations.scala | 45 +++++++++++++++++++++++--- src/dotty/tools/dotc/typer/Typer.scala | 12 ++++--- 3 files changed, 64 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index 2ad193970..356e68f72 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -461,6 +461,18 @@ object Denotations { current } + protected def bringForward()(implicit ctx: Context): SingleDenotation = this match { + case denot: SymDenotation if ctx.stillValid(denot) => + var d: SingleDenotation = denot + do { + d.validFor = Period(ctx.period.runId, d.validFor.firstPhaseId, d.validFor.lastPhaseId) + d = d.nextInRun + } while (d ne denot) + initial.copyIfParentInvalid + case _ => + staleSymbolError + } + /** Produce a denotation that is valid for the given context. * Usually called when !(validFor contains ctx.period) * (even though this is not a precondition). @@ -476,17 +488,6 @@ object Denotations { def current(implicit ctx: Context): SingleDenotation = { val currentPeriod = ctx.period val valid = myValidFor - def bringForward(): SingleDenotation = this match { - case denot: SymDenotation if ctx.stillValid(denot) => - var d: SingleDenotation = denot - do { - d.validFor = Period(currentPeriod.runId, d.validFor.firstPhaseId, d.validFor.lastPhaseId) - d = d.nextInRun - } while (d ne denot) - initial.copyIfParentInvalid - case _ => - staleSymbolError - } if (valid.runId != currentPeriod.runId) bringForward.current else { var cur = this @@ -530,7 +531,7 @@ object Denotations { } def staleSymbolError(implicit ctx: Context) = - throw new Error(s"stale symbol; $this, defined in run ${myValidFor.runId} is referred to in run ${ctx.period.runId}") + throw new StaleSymbol(s"stale symbol; $this, defined in run ${myValidFor.runId} is referred to in run ${ctx.period.runId}") /** For ClassDenotations only: * If caches influenced by parent classes are still valid, the denotation @@ -757,5 +758,7 @@ object Denotations { else NoSymbol } + + class StaleSymbol(msg: String) extends Exception(msg) } diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index d9fa15a5f..f6d86bd20 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -33,14 +33,23 @@ trait SymDenotations { this: Context => if (initFlags is Package) new PackageClassDenotation(symbol, owner, name, initFlags, initInfo, initPrivateWithin) else new ClassDenotation(symbol, owner, name, initFlags, initInfo, initPrivateWithin) else new SymDenotation(symbol, owner, name, initFlags, initInfo, initPrivateWithin) + result.firstRunId = ctx.runId result.validFor = stablePeriod result } - def stillValid(denot: SymDenotation): Boolean = + def stillValid(denot: SymDenotation): Boolean = try if (denot is ValidForever) true else if (denot.owner is PackageClass) denot.owner.decls.lookup(denot.name) eq denot.symbol - else stillValid(denot.owner) + else + stillValid(denot.owner) && ( + (denot.owner.firstRunId == denot.firstRunId) || { + println(s"no longer valid: $denot, was defined in ${denot.firstRunId}, owner ${denot.owner} was defined in ${denot.owner.firstRunId}") + false + }) + catch { + case ex: StaleSymbol => false + } } object SymDenotations { @@ -60,6 +69,8 @@ object SymDenotations { override def hasUniqueSym: Boolean = exists + private[SymDenotations] var firstRunId: RunId = _ + // ------ Getting and setting fields ----------------------------- private[this] var myFlags: FlagSet = adaptFlags(initFlags) @@ -720,6 +731,8 @@ object SymDenotations { val annotations1 = if (annotations != null) annotations else this.annotations val d = ctx.SymDenotation(symbol, owner, name, initFlags1, info1, privateWithin1) d.annotations = annotations1 + d.firstRunId = firstRunId + // what about validFor? d } } @@ -787,13 +800,37 @@ object SymDenotations { /** Are caches influenced by parent classes still valid? */ private def parentsAreValid(implicit ctx: Context): Boolean = parentDenots == null || - parentDenots.corresponds(myClassParents)(_ eq _.denot) + parentDenots.corresponds(myClassParents map (_.denot))(_ eq _) + + private var copied = 0 /** If caches influenced by parent classes are still valid, the denotation * itself, otherwise a freshly initialized copy. */ override def copyIfParentInvalid(implicit ctx: Context): SingleDenotation = - if (!parentsAreValid) copySymDenotation() else this + if (!parentsAreValid) { + println(s"parents of $this are invalid; copying $hashCode, symbol id = ${symbol.id} ...") + for ((pd1, pd2) <- parentDenots zip (myClassParents map (_.denot))) + if (pd1 ne pd2) println(s"different: $pd1 != $pd2") + if (name.toString == "Context") + new Error().printStackTrace() + assert(copied == 0) + copied += 1 + copySymDenotation() + } + else this + + protected override def bringForward()(implicit ctx: Context): SingleDenotation = { + if (name.toString == "Context") println(s"bring forward $this, id = ${symbol.id}, defunid = ${symbol.defRunId}, ctx.runid = ${ctx.runId}") + assert(ctx.runId >= symbol.defRunId, s"$this, defrunid = ${symbol.defRunId}, ctx.runid = ${ctx.runId}") + if (symbol.defRunId == ctx.runId) symbol.denot + else { + val d = super.bringForward() + symbol.denot = d.asSymDenotation + if (name.toString == "Context") println(s"brought forward $d, id = ${symbol.id}, defunid = ${symbol.defRunId}") + d + } + } // ------ class-specific operations ----------------------------------- diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index f48dfa09b..bce9d225a 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -65,10 +65,14 @@ class Typer extends Namer with Applications with Implicits { /** A denotation exists really if it exists and does not point to a stale symbol. */ def reallyExists(denot: Denotation)(implicit ctx: Context): Boolean = - denot.exists && { - val sym = denot.symbol - sym.ensureCompleted - (sym eq NoSymbol) || !sym.isAbsent + try + denot.exists && { + val sym = denot.symbol + sym.ensureCompleted + (sym eq NoSymbol) || !sym.isAbsent + } + catch { + case ex: StaleSymbol => false } /** The type of a selection with `name` of a tree with type `site`. -- cgit v1.2.3