Skip to content

Commit b8c5ecb

Browse files
authored
Fix stale symbols connected to lazy vals in macros (#21559)
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 #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).
2 parents 3ca6bd5 + c2287a2 commit b8c5ecb

File tree

4 files changed

+23
-1
lines changed

4 files changed

+23
-1
lines changed

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

+6-1
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, LazyType, stillValid, acceptStale, traceInvalid }
5+
import SymDenotations.{ SymDenotation, ClassDenotation, NoDenotation, LazyType, stillValid, movedToCompanionClass, acceptStale, traceInvalid }
66
import Contexts.*
77
import Names.*
88
import NameKinds.*
@@ -755,6 +755,11 @@ object Denotations {
755755
}
756756
if (!symbol.exists) return updateValidity()
757757
if (!coveredInterval.containsPhaseId(ctx.phaseId)) return NoDenotation
758+
// Moved to a companion class, likely at a later phase (in MoveStatics)
759+
this match {
760+
case symd: SymDenotation if movedToCompanionClass(symd) => return NoDenotation
761+
case _ =>
762+
}
758763
if (ctx.debug) traceInvalid(this)
759764
staleSymbolError
760765
}

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

+4
Original file line numberDiff line numberDiff line change
@@ -2680,6 +2680,10 @@ object SymDenotations {
26802680
stillValidInOwner(denot)
26812681
}
26822682

2683+
def movedToCompanionClass(denot: SymDenotation)(using Context): Boolean =
2684+
val ownerCompanion = denot.maybeOwner.companionClass
2685+
stillValid(ownerCompanion) && ownerCompanion.unforcedDecls.contains(denot.name, denot.symbol)
2686+
26832687
private[SymDenotations] def stillValidInOwner(denot: SymDenotation)(using Context): Boolean = try
26842688
val owner = denot.maybeOwner.denot
26852689
stillValid(owner)

tests/pos-macros/i21271/Macro.scala

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import scala.quoted.*
2+
3+
trait Schema
4+
object Schema:
5+
lazy val sampleDate: String = "" // lazy val requried to reproduce
6+
7+
inline def derived: Schema =
8+
annotations
9+
new Schema {}
10+
11+
inline def annotations: Int = ${ annotationsImpl }
12+
def annotationsImpl(using Quotes): Expr[Int] = Expr(1)

tests/pos-macros/i21271/Test.scala

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
val inputValueSchema = Schema.derived

0 commit comments

Comments
 (0)