diff options
author | Martin Odersky <odersky@gmail.com> | 2013-07-12 12:06:41 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2013-07-12 12:06:41 +0200 |
commit | e67de603b531ad268b906d77e900425e917c2a08 (patch) | |
tree | fa65ea3414982df73cccb5141c0138099214dfa2 /src/dotty/tools/dotc/core/Denotations.scala | |
parent | a466ae90c9ddf3d3312fb552fde106a8903383e1 (diff) | |
download | dotty-e67de603b531ad268b906d77e900425e917c2a08.tar.gz dotty-e67de603b531ad268b906d77e900425e917c2a08.tar.bz2 dotty-e67de603b531ad268b906d77e900425e917c2a08.zip |
Logic to ensure the following invariant: A class denotation's validity period is properly contained in the validty periods of all its parent classes. This is necessary to ensure that parent- and member-based caches in a ClassDenotation never become invalid.
Diffstat (limited to 'src/dotty/tools/dotc/core/Denotations.scala')
-rw-r--r-- | src/dotty/tools/dotc/core/Denotations.scala | 59 |
1 files changed, 30 insertions, 29 deletions
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index cb010ed8e..16c75e38b 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -407,11 +407,11 @@ object Denotations { // ------ Transformations ----------------------------------------- - private[this] var _validFor: Period = Nowhere + private[this] var myValidFor: Period = Nowhere - def validFor = _validFor + def validFor = myValidFor def validFor_=(p: Period) = - _validFor = p + myValidFor = p /** The next SingleDenotation in this run, with wrap-around from last to first. * @@ -434,7 +434,7 @@ object Denotations { */ def initial: SingleDenotation = { var current = nextInRun - while (current.validFor.code > this._validFor.code) current = current.nextInRun + while (current.validFor.code > this.myValidFor.code) current = current.nextInRun current } @@ -453,30 +453,25 @@ object Denotations { */ def current(implicit ctx: Context): SingleDenotation = { val currentPeriod = ctx.period - val valid = _validFor - def bringForward(): Unit = { - this match { - case NoDenotation => - validFor = Period(currentPeriod.runId, validFor.firstPhaseId, validFor.lastPhaseId) - return - case denot: SymDenotation => - val top = denot.topLevelSym - if (top.owner.info.decl(top.name).symbol == top) { - var d: SingleDenotation = denot - do { - d.validFor = Period(currentPeriod.runId, d.validFor.firstPhaseId, d.validFor.lastPhaseId) - d = d.nextInRun - } while (d ne denot) - return - } - case _ => + val valid = myValidFor + def stillValid(denot: SymDenotation) = + !denot.exists || { + val top = denot.topLevelSym + top.owner.info.decl(top.name).symbol eq top } - assert(false, s"stale symbol; ${symbol.showLocated}, defined in run ${valid.runId} is referred to in run ${currentPeriod.runId}") + def bringForward(): SingleDenotation = this match { + case denot: SymDenotation if 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 _ => + throw new Error(s"stale symbol; ${symbol.showLocated}, defined in run ${valid.runId} is referred to in run ${currentPeriod.runId}") } - if (valid.runId != currentPeriod.runId) { - bringForward() - current - } else { + if (valid.runId != currentPeriod.runId) bringForward.current + else { var cur = this if (currentPeriod.code > valid.code) { // search for containing period as long as nextInRun increases. @@ -494,7 +489,7 @@ object Denotations { var startPid = cur.validFor.lastPhaseId + 1 val transformers = ctx.transformersFor(cur) val transformer = transformers.nextTransformer(startPid) - next = transformer transform cur + next = transformer.transform(cur).copyIfParentInvalid if (next eq cur) startPid = cur.validFor.firstPhaseId else { @@ -508,16 +503,22 @@ object Denotations { // currentPeriod < valid; in this case a version must exist // but to be defensive we check for infinite loop anyway var cnt = 0 - do { + while (!(cur.validFor contains currentPeriod)) { cur = cur.nextInRun cnt += 1 assert(cnt <= MaxPossiblePhaseId) - } while (!(cur.validFor contains currentPeriod)) + } } cur } } + /** For ClassDenotations only: + * If caches influenced by parent classes are still valid, the denotation + * itself, otherwise a freshly initialized copy. + */ + def copyIfParentInvalid(implicit ctx: Context): SingleDenotation = this + final def asSymDenotation = asInstanceOf[SymDenotation] override def toString = |