diff --git a/compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala b/compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala index 32256e43d242..eab4c5d37d27 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)) makeSingletonMirror() + if (clazz.is(Case) && !linked.isGenericProduct) 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 73fc926b8893..025c8dbc23a5 100644 --- a/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala @@ -282,7 +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) - if module.info.classSymbol.is(Scala2x) then + if module.info.classSymbol.is(Scala2x) || module.companionClass.isGenericProduct then val mirrorType = mirrorCore(defn.Mirror_SingletonProxyClass, mirroredType, mirroredType, module.name, formal) val mirrorRef = New(defn.Mirror_SingletonProxyClass.typeRef, modulePath :: Nil) mirrorRef.cast(mirrorType) diff --git a/tests/run/i12919.scala b/tests/run/i12919.scala new file mode 100644 index 000000000000..8a32d16e2977 --- /dev/null +++ b/tests/run/i12919.scala @@ -0,0 +1,20 @@ +case class Normal(value: String) +object Normal + +case class ClassWithCaseCompanion(value: String) +case object ClassWithCaseCompanion + +def instantiate[T](product: Product)(implicit mirror: scala.deriving.Mirror.ProductOf[T]) = + mirror.fromProduct(product) + +@main def Test: Unit = { + assert(instantiate[Normal](Tuple1("a")) == Normal("a")) // works as expected + + assert(instantiate[ClassWithCaseCompanion.type](EmptyTuple) == ClassWithCaseCompanion) // works as expected + + val c = instantiate[ClassWithCaseCompanion](Tuple1("b")) // throws java.lang.ClassCastException: class ClassWithCaseCompanion$ cannot be cast to class ClassWithCaseCompanion + assert(c == ClassWithCaseCompanion("b")) // desired behaviour + + val d = instantiate[ClassWithCaseCompanion.type](EmptyTuple) + assert(d == ClassWithCaseCompanion) +}