Skip to content

Commit 0151a63

Browse files
committed
Reload denotations that are not defined at current phase
Up to now a NotDefinedHere exception was thrown if a denotation was not defined at the current phase, but was defined elsewhere in the current run. However, if the denotation is a SingleDenotation or MultiDenotation it is possible that the particular Single- or Multi-Denotation was not computed at the current phase, but the underlying SymDenotation is valid. With the changes in this commit, we reaload the denotation as a second try.
1 parent 09399bc commit 0151a63

File tree

3 files changed

+35
-10
lines changed

3 files changed

+35
-10
lines changed

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

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package dotty.tools
22
package dotc
33
package core
44

5-
import SymDenotations.{ SymDenotation, ClassDenotation, NoDenotation }
5+
import SymDenotations.{ SymDenotation, ClassDenotation, NoDenotation, NotDefinedHereDenotation }
66
import Contexts.{Context, ContextBase}
77
import Names.{Name, PreName}
88
import Names.TypeName
@@ -128,7 +128,17 @@ object Denotations {
128128
*/
129129
def atSignature(sig: Signature, site: Type = NoPrefix)(implicit ctx: Context): SingleDenotation
130130

131-
/** The variant of this denotation that's current in the given context. */
131+
/** The variant of this denotation that's current in the given context, or
132+
* `NotDefinedHereDenotation` if this denotation does not exist at current phase, but
133+
* is defined elsewhere in this run.
134+
*/
135+
def currentIfExists(implicit ctx: Context): Denotation
136+
137+
/** The variant of this denotation that's current in the given context.
138+
* If no such denotation exists: If Mode.FutureDefs is set, the
139+
* denotation with each alternative at its first point of definition,
140+
* otherwise a `NotDefinedHere` exception is thrown.
141+
*/
132142
def current(implicit ctx: Context): Denotation
133143

134144
/** Is this denotation different from NoDenotation or an ErrorDenotation? */
@@ -349,6 +359,8 @@ object Denotations {
349359
final def signature(implicit ctx: Context) = Signature.OverloadedSignature
350360
def atSignature(sig: Signature, site: Type)(implicit ctx: Context): SingleDenotation =
351361
denot1.atSignature(sig, site) orElse denot2.atSignature(sig, site)
362+
def currentIfExists(implicit ctx: Context): Denotation =
363+
derivedMultiDenotation(denot1.currentIfExists, denot2.currentIfExists)
352364
def current(implicit ctx: Context): Denotation =
353365
derivedMultiDenotation(denot1.current, denot2.current)
354366
def altsWith(p: Symbol => Boolean): List[SingleDenotation] =
@@ -530,7 +542,7 @@ object Denotations {
530542
* is brought forward to be valid in the new runId. Otherwise
531543
* the symbol is stale, which constitutes an internal error.
532544
*/
533-
def current(implicit ctx: Context): SingleDenotation = {
545+
def currentIfExists(implicit ctx: Context): SingleDenotation = {
534546
val currentPeriod = ctx.period
535547
val valid = myValidFor
536548
if (valid.code <= 0) {
@@ -593,17 +605,24 @@ object Denotations {
593605
//println(s"searching: $cur at $currentPeriod, valid for ${cur.validFor}")
594606
cur = cur.nextInRun
595607
cnt += 1
596-
if (cnt > MaxPossiblePhaseId)
597-
if (ctx.mode is Mode.FutureDefsOK)
598-
return current(ctx.withPhase(coveredInterval.firstPhaseId))
599-
else
600-
throw new NotDefinedHere(demandOutsideDefinedMsg)
608+
if (cnt > MaxPossiblePhaseId) return NotDefinedHereDenotation
601609
}
602610
cur
603611
}
604612
}
605613
}
606614

615+
def current(implicit ctx: Context): SingleDenotation = {
616+
val d = currentIfExists
617+
if (d ne NotDefinedHereDenotation) d else currentNoDefinedHere
618+
}
619+
620+
private def currentNoDefinedHere(implicit ctx: Context): SingleDenotation =
621+
if (ctx.mode is Mode.FutureDefsOK)
622+
current(ctx.withPhase(coveredInterval.firstPhaseId))
623+
else
624+
throw new NotDefinedHere(demandOutsideDefinedMsg)
625+
607626
private def demandOutsideDefinedMsg(implicit ctx: Context): String =
608627
s"demanding denotation of $this at phase ${ctx.phase}(${ctx.phaseId}) outside defined interval: defined periods are${definedPeriodsString}"
609628

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1650,7 +1650,7 @@ object SymDenotations {
16501650
}
16511651
}
16521652

1653-
object NoDenotation extends SymDenotation(
1653+
class NoDenotation extends SymDenotation(
16541654
NoSymbol, NoSymbol, "<none>".toTermName, Permanent, NoType) {
16551655
override def exists = false
16561656
override def isTerm = false
@@ -1660,6 +1660,9 @@ object SymDenotations {
16601660
validFor = Period.allInRun(NoRunId) // will be brought forward automatically
16611661
}
16621662

1663+
val NoDenotation = new NoDenotation
1664+
val NotDefinedHereDenotation = new NoDenotation
1665+
16631666
// ---- Completion --------------------------------------------------------
16641667

16651668
/** Instances of LazyType are carried by uncompleted symbols.

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1244,7 +1244,10 @@ object Types {
12441244
}
12451245
case d =>
12461246
if (d.validFor.runId != ctx.period.runId) loadDenot
1247-
else d.current
1247+
else {
1248+
val newd = d.currentIfExists
1249+
if (newd ne NotDefinedHereDenotation) newd else loadDenot
1250+
}
12481251
}
12491252
if (ctx.typerState.ephemeral) record("ephemeral cache miss: loadDenot")
12501253
else if (d.exists) {

0 commit comments

Comments
 (0)