Skip to content

Commit

Permalink
alternative: do not change parent type of companion
Browse files Browse the repository at this point in the history
  • Loading branch information
bishabosha committed Apr 21, 2022
1 parent d652f07 commit f3e8d83
Show file tree
Hide file tree
Showing 6 changed files with 19 additions and 36 deletions.
17 changes: 3 additions & 14 deletions compiler/src/dotty/tools/dotc/transform/SymUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -117,23 +117,12 @@ object SymUtils:
self.isOneOf(FinalOrInline, butNot = Mutable)
&& (!self.is(Method) || self.is(Accessor))

/** This module must use a `Mirror.SingletonProxy` for its mirror if:
* - it is Scala 2 defined
* - the companion class is a generic product or generic sum and would cache
* its mirror in this module.
*/
def requiresSingletonProxyMirror(using Context): Boolean =
self.is(Scala2x) || {
val cls = self.companionClass
cls.isGenericProduct
|| cls.useCompanionAsSumMirror && cls.isGenericSum(self)
}

def useCompanionAsSumMirror(using Context): Boolean =
def companionExtendsSum(using Context): Boolean =
self.linkedClass.isSubClass(defn.Mirror_SumClass)
self.linkedClass.exists
&& !self.is(Scala2x)
!self.is(Scala2x)
&& self.linkedClass.exists
&& !self.linkedClass.is(Case)
&& (
// 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
}

if (clazz.is(Module)) {
if (clazz.is(Case) && !clazz.requiresSingletonProxyMirror) makeSingletonMirror()
if (clazz.is(Case)) makeSingletonMirror()
else if (linked.isGenericProduct) makeProductMirror(linked)
else if (linked.isGenericSum(clazz)) makeSumMirror(linked)
else if (linked.is(Sealed))
Expand Down
7 changes: 2 additions & 5 deletions compiler/src/dotty/tools/dotc/typer/Synthesizer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -282,10 +282,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
if mirroredType.termSymbol.is(CaseVal) then
val module = mirroredType.termSymbol
val modulePath = pathFor(mirroredType).withSpan(span)
val requiresProxy =
val mClass = module.info.classSymbol
mClass.is(Module) && mClass.requiresSingletonProxyMirror
if requiresProxy then
if module.info.classSymbol.is(Scala2x) then
val mirrorType = mirrorCore(defn.Mirror_SingletonProxyClass, mirroredType, mirroredType, module.name, formal)
val mirrorRef = New(defn.Mirror_SingletonProxyClass.typeRef, modulePath :: Nil)
mirrorRef.cast(mirrorType)
Expand All @@ -310,7 +307,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
.refinedWith(tpnme.MirroredElemTypes, TypeAlias(elemsType))
.refinedWith(tpnme.MirroredElemLabels, TypeAlias(elemsLabels))
val mirrorRef =
if (cls.is(Scala2x)) anonymousMirror(monoType, ExtendsProductMirror, span)
if (cls.is(Scala2x) || cls.linkedClass.is(Case)) anonymousMirror(monoType, ExtendsProductMirror, span)
else companionPath(mirroredType, span)
mirrorRef.cast(mirrorType)
else EmptyTree
Expand Down
4 changes: 1 addition & 3 deletions library/src/scala/deriving/Mirror.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,7 @@ object Mirror {
def fromProduct(p: scala.Product): MirroredMonoType = this
}

/** A proxy for Scala 2 singletons (which do not inherit `Singleton` directly),
* or case objects with a case class companion
*/
/** A proxy for Scala 2 singletons, which do not inherit `Singleton` directly */
class SingletonProxy(val value: AnyRef) extends Product {
type MirroredMonoType = value.type
type MirroredType = value.type
Expand Down
19 changes: 9 additions & 10 deletions tests/run/i12919a.scala
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import scala.deriving.Mirror

class Standalone
case object Standalone
case class Standalone(i: Int)
object Standalone

case class WithCompanionCaseClass(i: Int)
case object WithCompanionCaseClass

@main def Test: Unit =

val mStandalone = summon[Mirror.Of[Standalone.type]]
assert(mStandalone eq Standalone) // the object is its own mirror
assert(mStandalone.isInstanceOf[Mirror.Singleton]) // object extends Mirror.Singleton because its its own mirror.
val mStandalone = summon[Mirror.ProductOf[Standalone]]
assert(mStandalone eq Standalone) // the companion object is the mirror for the case class

val mWithCompanion = summon[Mirror.Of[WithCompanionCaseClass.type]]
assert(mWithCompanion ne WithCompanionCaseClass) // the object is not its own mirror
assert(mWithCompanion.isInstanceOf[Mirror.SingletonProxy]) // its companion is a case class, so the mirror is a proxy
assert(!mWithCompanion.isInstanceOf[Mirror.Singleton]) // it can not extend Mirror.Singleton because its companion is a case class.
assert(WithCompanionCaseClass.isInstanceOf[Mirror.Product]) // its companion is a case class, so the mirror is a product.
val mWithCompanion = summon[Mirror.ProductOf[WithCompanionCaseClass]]
assert(mWithCompanion ne WithCompanionCaseClass) // A case object can not be the mirror of a companion case class.

val mWithCompanionCaseObject = summon[Mirror.ProductOf[WithCompanionCaseClass.type]]
assert(mWithCompanionCaseObject eq WithCompanionCaseClass) // A case object is its own mirror.
6 changes: 3 additions & 3 deletions tests/run/i12919b.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ case object WithCompanionSealedTrait:

val mWithCompanionSum = summon[Mirror.SumOf[WithCompanionSealedTrait]]
assert(mWithCompanionSum.ordinal(WithCompanionSealedTrait.FirstChild(1)) == 0)
assert(mWithCompanionSum eq WithCompanionSealedTrait) // case object caches sum mirror of its companion
assert(mWithCompanionSum ne WithCompanionSealedTrait) // A case object can not be the mirror of a companion case class.

val mWithCompanionSingleton = summon[Mirror.ProductOf[WithCompanionSealedTrait.type]]
assert(mWithCompanionSingleton.fromProduct(EmptyTuple) == WithCompanionSealedTrait)
assert(mWithCompanionSingleton.isInstanceOf[Mirror.SingletonProxy])
assert(mWithCompanionSingleton ne WithCompanionSealedTrait) // proxy mirror is never the object itself
assert(mWithCompanionSingleton.isInstanceOf[Mirror.Singleton]) // case object is its own mirror.
assert(mWithCompanionSingleton eq WithCompanionSealedTrait) // case object is its own mirror.

0 comments on commit f3e8d83

Please # to comment.