aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/Denotations.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-07-12 12:06:41 +0200
committerMartin Odersky <odersky@gmail.com>2013-07-12 12:06:41 +0200
commite67de603b531ad268b906d77e900425e917c2a08 (patch)
treefa65ea3414982df73cccb5141c0138099214dfa2 /src/dotty/tools/dotc/core/Denotations.scala
parenta466ae90c9ddf3d3312fb552fde106a8903383e1 (diff)
downloaddotty-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.scala59
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 =