Skip to content

Commit fecfbda

Browse files
authored
Fix validity period of derived SingleDenotations (#19983)
When running: val f: ( => Int) => Int = i => i ; f(1) twice in the REPL, the second time crashed with a ClassCastException. The difference is that in the second run, the denotation for `f.apply` is created from the SymDenotation for `Function1#apply` which already exists and is known to be valid in every phase, but that doesn't mean that the derived denotation for `f.apply` has the same validity: unlike the SymDenotation it needs to be transformed (in particular to run the `ElimByName` transformer). It turns out that there were multiple places in the compiler where we created a new denotation with a validity based on the existing one when this was not legitimate. I've gone through all these places and replaced them by `currentStablePeriod`. Fixes #18756.
2 parents c251f36 + 49571fa commit fecfbda

File tree

5 files changed

+30
-12
lines changed

5 files changed

+30
-12
lines changed

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,7 @@ object Denotations {
580580

581581
/** A non-overloaded denotation */
582582
abstract class SingleDenotation(symbol: Symbol, initInfo: Type, isType: Boolean) extends Denotation(symbol, initInfo, isType) {
583-
protected def newLikeThis(symbol: Symbol, info: Type, pre: Type, isRefinedMethod: Boolean): SingleDenotation
583+
protected def newLikeThis(symbol: Symbol, info: Type, pre: Type, isRefinedMethod: Boolean)(using Context): SingleDenotation
584584

585585
final def name(using Context): Name = symbol.name
586586

@@ -1162,11 +1162,11 @@ object Denotations {
11621162
prefix: Type) extends NonSymSingleDenotation(symbol, initInfo, prefix) {
11631163
validFor = initValidFor
11641164
override def hasUniqueSym: Boolean = true
1165-
protected def newLikeThis(s: Symbol, i: Type, pre: Type, isRefinedMethod: Boolean): SingleDenotation =
1165+
protected def newLikeThis(s: Symbol, i: Type, pre: Type, isRefinedMethod: Boolean)(using Context): SingleDenotation =
11661166
if isRefinedMethod then
1167-
new JointRefDenotation(s, i, validFor, pre, isRefinedMethod)
1167+
new JointRefDenotation(s, i, currentStablePeriod, pre, isRefinedMethod)
11681168
else
1169-
new UniqueRefDenotation(s, i, validFor, pre)
1169+
new UniqueRefDenotation(s, i, currentStablePeriod, pre)
11701170
}
11711171

11721172
class JointRefDenotation(
@@ -1177,15 +1177,15 @@ object Denotations {
11771177
override val isRefinedMethod: Boolean) extends NonSymSingleDenotation(symbol, initInfo, prefix) {
11781178
validFor = initValidFor
11791179
override def hasUniqueSym: Boolean = false
1180-
protected def newLikeThis(s: Symbol, i: Type, pre: Type, isRefinedMethod: Boolean): SingleDenotation =
1181-
new JointRefDenotation(s, i, validFor, pre, isRefinedMethod)
1180+
protected def newLikeThis(s: Symbol, i: Type, pre: Type, isRefinedMethod: Boolean)(using Context): SingleDenotation =
1181+
new JointRefDenotation(s, i, currentStablePeriod, pre, isRefinedMethod)
11821182
}
11831183

11841184
class ErrorDenotation(using Context) extends NonSymSingleDenotation(NoSymbol, NoType, NoType) {
11851185
override def exists: Boolean = false
11861186
override def hasUniqueSym: Boolean = false
11871187
validFor = Period.allInRun(ctx.runId)
1188-
protected def newLikeThis(s: Symbol, i: Type, pre: Type, isRefinedMethod: Boolean): SingleDenotation =
1188+
protected def newLikeThis(s: Symbol, i: Type, pre: Type, isRefinedMethod: Boolean)(using Context): SingleDenotation =
11891189
this
11901190
}
11911191

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1624,11 +1624,11 @@ object SymDenotations {
16241624

16251625
// ----- copies and transforms ----------------------------------------
16261626

1627-
protected def newLikeThis(s: Symbol, i: Type, pre: Type, isRefinedMethod: Boolean): SingleDenotation =
1627+
protected def newLikeThis(s: Symbol, i: Type, pre: Type, isRefinedMethod: Boolean)(using Context): SingleDenotation =
16281628
if isRefinedMethod then
1629-
new JointRefDenotation(s, i, validFor, pre, isRefinedMethod)
1629+
new JointRefDenotation(s, i, currentStablePeriod, pre, isRefinedMethod)
16301630
else
1631-
new UniqueRefDenotation(s, i, validFor, pre)
1631+
new UniqueRefDenotation(s, i, currentStablePeriod, pre)
16321632

16331633
/** Copy this denotation, overriding selective fields */
16341634
final def copySymDenotation(

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -905,7 +905,7 @@ object Types extends TypeUtils {
905905
def goSuper(tp: SuperType) = go(tp.underlying) match {
906906
case d: JointRefDenotation =>
907907
typr.println(i"redirecting super.$name from $tp to ${d.symbol.showLocated}")
908-
new UniqueRefDenotation(d.symbol, tp.memberInfo(d.symbol), d.validFor, pre)
908+
new UniqueRefDenotation(d.symbol, tp.memberInfo(d.symbol), currentStablePeriod, pre)
909909
case d => d
910910
}
911911

compiler/src/dotty/tools/dotc/transform/Erasure.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import core.Types.*
1313
import core.Names.*
1414
import core.StdNames.*
1515
import core.NameOps.*
16+
import core.Periods.currentStablePeriod
1617
import core.NameKinds.{AdaptedClosureName, BodyRetainerName, DirectMethName}
1718
import core.Scopes.newScopeWith
1819
import core.Decorators.*
@@ -132,7 +133,7 @@ class Erasure extends Phase with DenotTransformer {
132133
}
133134
case ref: JointRefDenotation =>
134135
new UniqueRefDenotation(
135-
ref.symbol, transformInfo(ref.symbol, ref.symbol.info), ref.validFor, ref.prefix)
136+
ref.symbol, transformInfo(ref.symbol, ref.symbol.info), currentStablePeriod, ref.prefix)
136137
case _ =>
137138
ref.derivedSingleDenotation(ref.symbol, transformInfo(ref.symbol, ref.symbol.info))
138139
}

compiler/test-resources/repl/i18756

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
scala> object A { val f: ( => Int) => Int = i => i ; f(1) }
2+
// defined object A
3+
4+
scala> A.f(1)
5+
val res0: Int = 1
6+
7+
scala> A.f(1)
8+
val res1: Int = 1
9+
10+
scala> object B { val f: ( => Int) => Int = i => i ; f(1) }
11+
// defined object B
12+
13+
scala> B.f(1)
14+
val res2: Int = 1
15+
16+
scala> B.f(1)
17+
val res3: Int = 1

0 commit comments

Comments
 (0)