Skip to content

Commit

Permalink
Merge pull request #14986 from dotty-staging/fix-12919
Browse files Browse the repository at this point in the history
  • Loading branch information
dwijnand authored May 5, 2022
2 parents 2309212 + 6841f9c commit 06a8f22
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 3 deletions.
5 changes: 3 additions & 2 deletions compiler/src/dotty/tools/dotc/transform/SymUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,9 @@ object SymUtils:
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
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/Synthesizer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -307,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
20 changes: 20 additions & 0 deletions tests/run/i12919.scala
Original file line number Diff line number Diff line change
@@ -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)
}
18 changes: 18 additions & 0 deletions tests/run/i12919a.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import scala.deriving.Mirror

case class Standalone(i: Int)
object Standalone

case class WithCompanionCaseClass(i: Int)
case object WithCompanionCaseClass

@main def Test: Unit =

val mStandalone = summon[Mirror.ProductOf[Standalone]]
assert(mStandalone eq Standalone) // the companion object is the mirror for the case class

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.
17 changes: 17 additions & 0 deletions tests/run/i12919b.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import scala.deriving.Mirror


sealed trait WithCompanionSealedTrait
case object WithCompanionSealedTrait:
case class FirstChild(x: Int) extends WithCompanionSealedTrait

@main def Test: Unit =

val mWithCompanionSum = summon[Mirror.SumOf[WithCompanionSealedTrait]]
assert(mWithCompanionSum.ordinal(WithCompanionSealedTrait.FirstChild(1)) == 0)
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.Singleton]) // case object is its own mirror.
assert(mWithCompanionSingleton eq WithCompanionSealedTrait) // case object is its own mirror.
10 changes: 10 additions & 0 deletions tests/run/i15101.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
trait Encoder[T]
object Encoder:
def derived[T](using scala.deriving.Mirror.Of[T]): Encoder[T] = new Encoder[T] {}

case object Bar
enum Bar derives Encoder:
case A, B

@main def Test: Unit =
summon[Encoder[Bar]]

0 comments on commit 06a8f22

Please # to comment.