diff --git a/compiler/src/dotty/tools/dotc/transform/SymUtils.scala b/compiler/src/dotty/tools/dotc/transform/SymUtils.scala index aededd7a5f9e..39c9aae52207 100644 --- a/compiler/src/dotty/tools/dotc/transform/SymUtils.scala +++ b/compiler/src/dotty/tools/dotc/transform/SymUtils.scala @@ -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 diff --git a/compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala b/compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala index d12280d0e7ce..32256e43d242 100644 --- a/compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala +++ b/compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala @@ -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)) diff --git a/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala b/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala index 66b8a69f514e..03554cbabea6 100644 --- a/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala @@ -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) @@ -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 diff --git a/library/src/scala/deriving/Mirror.scala b/library/src/scala/deriving/Mirror.scala index 90be5969ce5f..d091f4ee559e 100644 --- a/library/src/scala/deriving/Mirror.scala +++ b/library/src/scala/deriving/Mirror.scala @@ -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 diff --git a/tests/run/i12919a.scala b/tests/run/i12919a.scala index 7e460c9ac48c..1f7abcfdc4e9 100644 --- a/tests/run/i12919a.scala +++ b/tests/run/i12919a.scala @@ -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. diff --git a/tests/run/i12919b.scala b/tests/run/i12919b.scala index 7946bec7aac5..84d9277c0a04 100644 --- a/tests/run/i12919b.scala +++ b/tests/run/i12919b.scala @@ -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.