Skip to content

Commit

Permalink
check defined in src for cache in companion
Browse files Browse the repository at this point in the history
  • Loading branch information
bishabosha committed Feb 24, 2022
1 parent 2333316 commit 85eb50a
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 11 deletions.
14 changes: 14 additions & 0 deletions compiler/src/dotty/tools/dotc/core/Symbols.scala
Expand Up @@ -143,6 +143,20 @@ object Symbols {
false
}

/** Is this symbol valid in the current run and has an associated file that is
* not a binary file. e.g. This will return true for
* symbols defined by the user in a prior run of the REPL, that are still valid.
*/
final def isDefinedInSource(using Context): Boolean =
span.exists && isValidInCurrentRun && {
try
val file = associatedFile
file != null && file.extension != "class"
catch case ex: StaleSymbol =>
// can happen for constructor proxy companions. Test case is pos-macros/i9484.
false
}

/** Is symbol valid in current run? */
final def isValidInCurrentRun(using Context): Boolean =
(lastDenot.validFor.runId == ctx.runId || stillValid(lastDenot)) &&
Expand Down
23 changes: 12 additions & 11 deletions compiler/src/dotty/tools/dotc/transform/SymUtils.scala
Expand Up @@ -111,18 +111,19 @@ object SymUtils:
self.isAllOf(Given | Method) && isCodefined(self.info)

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

/** Is this a sealed class or trait for which a sum mirror is generated?
* It must satisfy the following conditions:
Expand Down
7 changes: 7 additions & 0 deletions compiler/test-resources/repl/i14540
@@ -0,0 +1,7 @@
scala> enum I14540 { case A }
// defined class I14540
scala> summon[scala.deriving.Mirror.SumOf[I14540]] eq I14540
val res0: Boolean = true
scala> enum I14540B { case A }; summon[scala.deriving.Mirror.SumOf[I14540B]] eq I14540B
// defined class I14540B
val res1: Boolean = true
Expand Up @@ -5,4 +5,5 @@ import scala.deriving.Mirror
object Main:
def main(args: Array[String]): Unit =
val mirrorTop = summon[Mirror.SumOf[lib.Top]]
assert(mirrorTop ne lib.Top) // **NOT** cached in companion - previous run, pre-3.1 tasty dependency
assert(mirrorTop.ordinal(lib.Middle()) == 0)
7 changes: 7 additions & 0 deletions tests/run/i14540-priorRun/Lib_1.scala
@@ -0,0 +1,7 @@
package lib

sealed trait Top
object Top // companion is necessary

case class Middle() extends Top with Bottom
sealed trait Bottom extends Top
6 changes: 6 additions & 0 deletions tests/run/i14540-priorRun/Test_2.scala
@@ -0,0 +1,6 @@
import scala.deriving.Mirror

@main def Test =
val mirrorTop = summon[Mirror.SumOf[lib.Top]]
assert(mirrorTop eq lib.Top) // cached in companion - previous run, tasty dependency
assert(mirrorTop.ordinal(lib.Middle()) == 0)
7 changes: 7 additions & 0 deletions tests/run/i14540-sameRun/Lib.scala
@@ -0,0 +1,7 @@
package lib

sealed trait Top
object Top // companion is necessary

case class Middle() extends Top with Bottom
sealed trait Bottom extends Top
6 changes: 6 additions & 0 deletions tests/run/i14540-sameRun/Test.scala
@@ -0,0 +1,6 @@
import scala.deriving.Mirror

@main def Test =
val mirrorTop = summon[Mirror.SumOf[lib.Top]]
assert(mirrorTop eq lib.Top) // cached in companion - same run, source dependency
assert(mirrorTop.ordinal(lib.Middle()) == 0)

0 comments on commit 85eb50a

Please sign in to comment.