From 968d16c289aedc7532dae9225502789b507e22e3 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 3 Jul 2014 18:51:50 +0200 Subject: Fixed problem with installAfter The problem is that when an installAfter completely replaces a previous denotation, a symbol or NamedType might still hang on to that denotation in the cache. We need to enforce that we switch to the new denotation. This is done by setting the replaced denotation's validFor field to Nowhere. --- src/dotty/tools/dotc/core/Denotations.scala | 32 +++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) (limited to 'src/dotty') diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index bdc67aa08..82ee6560d 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -512,7 +512,13 @@ object Denotations { def current(implicit ctx: Context): SingleDenotation = { val currentPeriod = ctx.period val valid = myValidFor - assert(valid.code > 0) + if (valid.code <= 0) { + // can happen if we sit on a stale denotation which has been replaced + // wholesale by an installAfter; in this case, proceed to the next + // denotation and try again. + if (validFor == Nowhere && nextInRun.validFor != Nowhere) return nextInRun.current + assert(false) + } if (valid.runId != currentPeriod.runId) bringForward.current else { @@ -551,6 +557,7 @@ object Denotations { cur = next } cur.validFor = Period(currentPeriod.runId, startPid, transformer.lastPhaseId) + //printPeriods(cur) //println(s"new denot: $cur, valid for ${cur.validFor}") } cur.current // multiple transformations could be required @@ -563,7 +570,11 @@ object Denotations { //println(s"searching: $cur at $currentPeriod, valid for ${cur.validFor}") cur = cur.nextInRun cnt += 1 - assert(cnt <= MaxPossiblePhaseId, s"seems to be a loop in Denotations for $this, currentPeriod = $currentPeriod") + if (cnt > MaxPossiblePhaseId) { + println(s"seems to be a loop in Denotations for $this, currentPeriod = $currentPeriod") + printPeriods(this) + assert(false) + } } cur } @@ -571,6 +582,19 @@ object Denotations { } } + private def printPeriods(current: SingleDenotation): Unit = { + print(s"periods for $this:") + var cur = current + var cnt = 0 + do { + print(" " + cur.validFor) + cur = cur.nextInRun + cnt += 1 + if (cnt > MaxPossiblePhaseId) { println(" ..."); return } + } while (cur ne current) + println() + } + /** Install this denotation to be the result of the given denotation transformer. * This is the implementation of the same-named method in SymDenotations. * It's placed here because it needs access to private fields of SingleDenotation. @@ -581,6 +605,8 @@ object Denotations { assert(ctx.phaseId == targetId, s"denotation update for $this called in phase ${ctx.phase}, expected was ${phase.next}") val current = symbol.current + // println(s"installing $this after $phase/${phase.id}, valid = ${current.validFor}") + // printPeriods(current) this.nextInRun = current.nextInRun this.validFor = Period(ctx.runId, targetId, current.validFor.lastPhaseId) if (current.validFor.firstPhaseId == targetId) { @@ -588,12 +614,14 @@ object Denotations { var prev = current while (prev.nextInRun ne current) prev = prev.nextInRun prev.nextInRun = this + current.validFor = Nowhere } else { // insert this denotation after current current.validFor = Period(ctx.runId, current.validFor.firstPhaseId, targetId - 1) current.nextInRun = this } + // printPeriods(this) } def staleSymbolError(implicit ctx: Context) = { -- cgit v1.2.3