Skip to content

Commit b98e6bf

Browse files
committed
Merge pull request #1200 from dotty-staging/docs-denotations
Docs and polishing for denotation insertions
2 parents 3ef4115 + 27e5c21 commit b98e6bf

File tree

1 file changed

+29
-12
lines changed

1 file changed

+29
-12
lines changed

src/dotty/tools/dotc/core/Denotations.scala

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -655,8 +655,7 @@ object Denotations {
655655
next.resetFlag(Frozen)
656656
case _ =>
657657
}
658-
next.nextInRun = cur.nextInRun
659-
cur.nextInRun = next
658+
next.insertAfter(cur)
660659
cur = next
661660
}
662661
cur.validFor = Period(currentPeriod.runId, startPid, transformer.lastPhaseId)
@@ -672,6 +671,10 @@ object Denotations {
672671
while (!(cur.validFor contains currentPeriod)) {
673672
//println(s"searching: $cur at $currentPeriod, valid for ${cur.validFor}")
674673
cur = cur.nextInRun
674+
// Note: One might be tempted to add a `prev` field to get to the new denotation
675+
// more directly here. I tried that, but it degrades rather than improves
676+
// performance: Test setup: Compile everything in dotc and immediate subdirectories
677+
// 10 times. Best out of 10: 18154ms with `prev` field, 17777ms without.
675678
cnt += 1
676679
if (cnt > MaxPossiblePhaseId) return NotDefinedHereDenotation
677680
}
@@ -708,12 +711,10 @@ object Denotations {
708711
// printPeriods(current)
709712
this.validFor = Period(ctx.runId, targetId, current.validFor.lastPhaseId)
710713
if (current.validFor.firstPhaseId >= targetId)
711-
replaceDenotation(current)
714+
insertInsteadOf(current)
712715
else {
713-
// insert this denotation after current
714716
current.validFor = Period(ctx.runId, current.validFor.firstPhaseId, targetId - 1)
715-
this.nextInRun = current.nextInRun
716-
current.nextInRun = this
717+
insertAfter(current)
717718
}
718719
// printPeriods(this)
719720
}
@@ -731,19 +732,35 @@ object Denotations {
731732
val current1: SingleDenotation = f(current.asSymDenotation)
732733
if (current1 ne current) {
733734
current1.validFor = current.validFor
734-
current1.replaceDenotation(current)
735+
current1.insertInsteadOf(current)
735736
}
736737
hasNext = current1.nextInRun.validFor.code > current1.validFor.code
737738
current = current1.nextInRun
738739
}
739740
}
740741

741-
private def replaceDenotation(current: SingleDenotation): Unit = {
742-
var prev = current
743-
while (prev.nextInRun ne current) prev = prev.nextInRun
742+
/** Insert this denotation so that it follows `prev`. */
743+
private def insertAfter(prev: SingleDenotation) = {
744+
this.nextInRun = prev.nextInRun
744745
prev.nextInRun = this
745-
this.nextInRun = current.nextInRun
746-
current.validFor = Nowhere
746+
}
747+
748+
/** Insert this denotation instead of `old`.
749+
* Also ensure that `old` refers with `nextInRun` to this denotation
750+
* and set its `validFor` field to `NoWhere`. This is necessary so that
751+
* references to the old denotation can be brought forward via `current`
752+
* to a valid denotation.
753+
*
754+
* The code to achieve this is subtle in that it works correctly
755+
* whether the replaced denotation is the only one in its cycle or not.
756+
*/
757+
private def insertInsteadOf(old: SingleDenotation): Unit = {
758+
var prev = old
759+
while (prev.nextInRun ne old) prev = prev.nextInRun
760+
// order of next two assignments is important!
761+
prev.nextInRun = this
762+
this.nextInRun = old.nextInRun
763+
old.validFor = Nowhere
747764
}
748765

749766
def staleSymbolError(implicit ctx: Context) = {

0 commit comments

Comments
 (0)