Skip to content

Commit 85eb50a

Browse files
committed
check defined in src for cache in companion
1 parent 2333316 commit 85eb50a

File tree

8 files changed

+60
-11
lines changed

8 files changed

+60
-11
lines changed

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,20 @@ object Symbols {
143143
false
144144
}
145145

146+
/** Is this symbol valid in the current run and has an associated file that is
147+
* not a binary file. e.g. This will return true for
148+
* symbols defined by the user in a prior run of the REPL, that are still valid.
149+
*/
150+
final def isDefinedInSource(using Context): Boolean =
151+
span.exists && isValidInCurrentRun && {
152+
try
153+
val file = associatedFile
154+
file != null && file.extension != "class"
155+
catch case ex: StaleSymbol =>
156+
// can happen for constructor proxy companions. Test case is pos-macros/i9484.
157+
false
158+
}
159+
146160
/** Is symbol valid in current run? */
147161
final def isValidInCurrentRun(using Context): Boolean =
148162
(lastDenot.validFor.runId == ctx.runId || stillValid(lastDenot)) &&

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

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -111,18 +111,19 @@ object SymUtils:
111111
self.isAllOf(Given | Method) && isCodefined(self.info)
112112

113113
def useCompanionAsSumMirror(using Context): Boolean =
114+
def companionExtendsSum(using Context): Boolean =
115+
self.linkedClass.isSubClass(defn.Mirror_SumClass)
114116
self.linkedClass.exists
115-
&& !self.is(Scala2x)
116-
&& (
117-
// If the sum type is compiled from source, and `self` is a "generic sum"
118-
// then its companion object will become a sum mirror in `posttyper`. (This method
119-
// can be called from `typer` when summoning a Mirror.)
120-
// However if `self` is from a prior run then we should check that its companion subclasses `Mirror.Sum`.
121-
// e.g. before Scala 3.1, hierarchical sum types were not considered "generic sums", so their
122-
// companion would not cache the mirror. Companions from TASTy will already be typed as `Mirror.Sum`.
123-
self.isDefinedInCurrentRun
124-
|| self.linkedClass.isSubClass(defn.Mirror_SumClass)
125-
)
117+
&& !self.is(Scala2x)
118+
&& (
119+
// If the sum type is compiled from source, and `self` is a "generic sum"
120+
// then its companion object will become a sum mirror in `posttyper`. (This method
121+
// can be called from `typer` when summoning a Mirror.)
122+
// However if `self` is from a prior run then we should check that its companion subclasses `Mirror.Sum`.
123+
// e.g. before Scala 3.1, hierarchical sum types were not considered "generic sums", so their
124+
// companion would not cache the mirror. Companions from TASTy will already be typed as `Mirror.Sum`.
125+
self.isDefinedInSource || companionExtendsSum
126+
)
126127

127128
/** Is this a sealed class or trait for which a sum mirror is generated?
128129
* It must satisfy the following conditions:

compiler/test-resources/repl/i14540

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
scala> enum I14540 { case A }
2+
// defined class I14540
3+
scala> summon[scala.deriving.Mirror.SumOf[I14540]] eq I14540
4+
val res0: Boolean = true
5+
scala> enum I14540B { case A }; summon[scala.deriving.Mirror.SumOf[I14540B]] eq I14540B
6+
// defined class I14540B
7+
val res1: Boolean = true

sbt-test/scala3-backcompat/hierarchical-mirrors/app/Main.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ import scala.deriving.Mirror
55
object Main:
66
def main(args: Array[String]): Unit =
77
val mirrorTop = summon[Mirror.SumOf[lib.Top]]
8+
assert(mirrorTop ne lib.Top) // **NOT** cached in companion - previous run, pre-3.1 tasty dependency
89
assert(mirrorTop.ordinal(lib.Middle()) == 0)

tests/run/i14540-priorRun/Lib_1.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package lib
2+
3+
sealed trait Top
4+
object Top // companion is necessary
5+
6+
case class Middle() extends Top with Bottom
7+
sealed trait Bottom extends Top
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import scala.deriving.Mirror
2+
3+
@main def Test =
4+
val mirrorTop = summon[Mirror.SumOf[lib.Top]]
5+
assert(mirrorTop eq lib.Top) // cached in companion - previous run, tasty dependency
6+
assert(mirrorTop.ordinal(lib.Middle()) == 0)

tests/run/i14540-sameRun/Lib.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package lib
2+
3+
sealed trait Top
4+
object Top // companion is necessary
5+
6+
case class Middle() extends Top with Bottom
7+
sealed trait Bottom extends Top

tests/run/i14540-sameRun/Test.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import scala.deriving.Mirror
2+
3+
@main def Test =
4+
val mirrorTop = summon[Mirror.SumOf[lib.Top]]
5+
assert(mirrorTop eq lib.Top) // cached in companion - same run, source dependency
6+
assert(mirrorTop.ordinal(lib.Middle()) == 0)

0 commit comments

Comments
 (0)