Skip to content

Commit

Permalink
Fix stale symbols connected to lazy vals in macros (scala#21559)
Browse files Browse the repository at this point in the history
While bringing forward the denotation to a new run, we now check if the
symbol was moved from its owner to a companion object. If so, we return
NoDenotation, as that denotation seems to be a leftover from
pre-MoveStatics phases in a previous run.

In the issue reproduction, we had a symbol created in the `LazyVals`
phase, which was then later moved to a companion class in `MoveStatics`
in the first run. In the second run, this caused the leftover denotation
for pre-MoveStatics phases of the first run to be tried to brought
forward (since the phaseID became valid at that point), failing to do so
(because that symbol should no longer exist as a member of the initial
companion object at that point).

It looks like before scala#19786, since this denotation was valid at a later
phase, it would be visited somewhere before the MegaPhase with
`LazyVals` and replaced with a NoDenotation (pretty much by accident),
which back then ended up being cached for the latter phases as well.

So in the fix here we check for that specific `MoveStatics` -caused case
and, if found, update the symbol with a NoDenotation (just like before,
but this time, on purpose).
  • Loading branch information
jchyb authored Sep 23, 2024
2 parents 3ca6bd5 + c2287a2 commit b8c5ecb
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 1 deletion.
7 changes: 6 additions & 1 deletion compiler/src/dotty/tools/dotc/core/Denotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package dotty.tools
package dotc
package core

import SymDenotations.{ SymDenotation, ClassDenotation, NoDenotation, LazyType, stillValid, acceptStale, traceInvalid }
import SymDenotations.{ SymDenotation, ClassDenotation, NoDenotation, LazyType, stillValid, movedToCompanionClass, acceptStale, traceInvalid }
import Contexts.*
import Names.*
import NameKinds.*
Expand Down Expand Up @@ -755,6 +755,11 @@ object Denotations {
}
if (!symbol.exists) return updateValidity()
if (!coveredInterval.containsPhaseId(ctx.phaseId)) return NoDenotation
// Moved to a companion class, likely at a later phase (in MoveStatics)
this match {
case symd: SymDenotation if movedToCompanionClass(symd) => return NoDenotation
case _ =>
}
if (ctx.debug) traceInvalid(this)
staleSymbolError
}
Expand Down
4 changes: 4 additions & 0 deletions compiler/src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2680,6 +2680,10 @@ object SymDenotations {
stillValidInOwner(denot)
}

def movedToCompanionClass(denot: SymDenotation)(using Context): Boolean =
val ownerCompanion = denot.maybeOwner.companionClass
stillValid(ownerCompanion) && ownerCompanion.unforcedDecls.contains(denot.name, denot.symbol)

private[SymDenotations] def stillValidInOwner(denot: SymDenotation)(using Context): Boolean = try
val owner = denot.maybeOwner.denot
stillValid(owner)
Expand Down
12 changes: 12 additions & 0 deletions tests/pos-macros/i21271/Macro.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import scala.quoted.*

trait Schema
object Schema:
lazy val sampleDate: String = "" // lazy val requried to reproduce

inline def derived: Schema =
annotations
new Schema {}

inline def annotations: Int = ${ annotationsImpl }
def annotationsImpl(using Quotes): Expr[Int] = Expr(1)
1 change: 1 addition & 0 deletions tests/pos-macros/i21271/Test.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
val inputValueSchema = Schema.derived

0 comments on commit b8c5ecb

Please sign in to comment.