Skip to content

Commit 41a5e1b

Browse files
committed
Invalidate some denotations in earlier phases
This addresses the specific problem raised by #10044: A denotation of a NamedType goes from a UniqueRefDenotation to a SymDenotation after erasure and is then not reset to the original since the SymDenotation is valid at all phases. We remember in this case in the NamedType the first phase in which the SymDenotaton is valid and force a recompute in earlier phases. Fixes #10044
1 parent 9b40981 commit 41a5e1b

File tree

2 files changed

+24
-0
lines changed

2 files changed

+24
-0
lines changed

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2097,6 +2097,7 @@ object Types {
20972097
private var lastDenotation: Denotation | Null = null
20982098
private var lastSymbol: Symbol | Null = null
20992099
private var checkedPeriod: Period = Nowhere
2100+
private var firstValidPhaseId: Int = 0
21002101
private var myStableHash: Byte = 0
21012102
private var mySignature: Signature = _
21022103
private var mySignatureRunId: Int = NoRunId
@@ -2212,6 +2213,8 @@ object Types {
22122213
val now = ctx.period
22132214
// Even if checkedPeriod == now we still need to recheck lastDenotation.validFor
22142215
// as it may have been mutated by SymDenotation#installAfter
2216+
if firstValidPhaseId > now.phaseId then
2217+
revalidateDenot()
22152218
if (checkedPeriod != Nowhere && lastDenotation.nn.validFor.contains(now)) {
22162219
checkedPeriod = now
22172220
lastDenotation.nn
@@ -2570,6 +2573,15 @@ object Types {
25702573
|| adapted.info.eq(denot.info))
25712574
adapted
25722575
else this
2576+
val lastDenot = result.lastDenotation
2577+
if denot.isInstanceOf[SymDenotation] && lastDenot != null && !lastDenot.isInstanceOf[SymDenotation] then
2578+
// In this case the new SymDenotation might be valid for all phases, which means
2579+
// we would not recompute the denotation when travelling to an earlier phase, maybe
2580+
// in the next run. We fix that problem by recording in this case in the NamedType
2581+
// the phase from which the denotation is valid. Taking the denotation at an earlier
2582+
// phase will then lead to a `revalidateDenot`.
2583+
core.println(i"overwrite ${result.toString} / ${result.lastDenotation} with $denot")
2584+
result.firstValidPhaseId = ctx.phaseId
25732585
result.setDenot(denot)
25742586
result.asInstanceOf[ThisType]
25752587
}

compiler/test-resources/repl/i10044

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
scala> object Foo { opaque type Bar = Int; object Bar { extension (b: Bar) def flip: Bar = -b; def apply(x: Int): Bar = x }}
2+
// defined object Foo
3+
scala> val a = Foo.Bar(42)
4+
val a: Foo.Bar = 42
5+
scala> val b = a.flip
6+
val b: Foo.Bar = -42
7+
scala> val c = b.flip
8+
val c: Foo.Bar = 42
9+
scala> val d = c.flip
10+
val d: Foo.Bar = -42
11+
scala> val e = d.flip
12+
val e: Foo.Bar = 42

0 commit comments

Comments
 (0)