Skip to content

Commit 970c389

Browse files
committed
Allow derivation for classes with no companions
Two problems needed to be fixed - deciding that the derived type is the companion, not the synthetic companion - Avoiding forcing `Shape` types in checkRealizable since these can compute `children` too early.
1 parent 0bf30ce commit 970c389

File tree

3 files changed

+12
-7
lines changed

3 files changed

+12
-7
lines changed

compiler/src/dotty/tools/dotc/core/CheckRealizable.scala

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,11 @@ class CheckRealizable(implicit ctx: Context) {
105105
/** `Realizable` if `tp` has good bounds, a `HasProblem...` instance
106106
* pointing to a bad bounds member otherwise. "Has good bounds" means:
107107
*
108-
* - all type members have good bounds (except for opaque helpers)
108+
* - all non-synthetic type members have good bounds.
109+
* Synthetic members are unchecked, for two reasons:
110+
* - synthetic opaque aliases do have conflicting bounds, but this is OK
111+
* - we should not force synthesized Shape types because that might
112+
* query the `children` annotation too early.
109113
* - all refinements of the underlying type have good bounds (except for opaque companions)
110114
* - all base types are class types, and if their arguments are wildcards
111115
* they have good bounds.
@@ -123,7 +127,8 @@ class CheckRealizable(implicit ctx: Context) {
123127
val memberProblems =
124128
for {
125129
mbr <- tp.nonClassTypeMembers
126-
if !(mbr.info.loBound <:< mbr.info.hiBound) && !mbr.symbol.isOpaqueHelper
130+
if !mbr.symbol.is(Synthetic)
131+
if !(mbr.info.loBound <:< mbr.info.hiBound)
127132
}
128133
yield new HasProblemBounds(mbr.name, mbr.info)
129134

compiler/src/dotty/tools/dotc/typer/Namer.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -988,7 +988,8 @@ class Namer { typer: Typer =>
988988

989989
if (impl.derived.nonEmpty) {
990990
val derivingClass =
991-
if (original.removeAttachment(DerivingCompanion).isDefined) cls.companionClass.asClass
991+
if (original.removeAttachment(DerivingCompanion).isDefined ||
992+
original.mods.is(Synthetic)) cls.companionClass.asClass
992993
else cls
993994
val deriver = new Deriver(derivingClass, impl.pos.startPos)(localCtx)
994995
deriver.enterDerived(impl.derived)

tests/run/typeclass-derivation3.scala

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,24 @@ import scala.annotation.tailrec
33

44
object datatypes {
55
import typeclasses._
6+
67
// An algebraic datatype
78
enum Lst[+T] derives Eq, Pickler, Show {
89
case Cons(hd: T, tl: Lst[T])
910
case Nil
1011
}
11-
1212
object Lst {}
1313

14+
1415
// A simple product type
1516
case class Pair[T](x: T, y: T) derives Eq, Pickler, Show
16-
object Pair
1717

1818
// another ADT
1919
sealed trait Either[+L, +R] extends Product derives Eq, Pickler, Show
2020
case class Left[L](x: L) extends Either[L, Nothing]
2121
case class Right[R](x: R) extends Either[Nothing, R]
2222

23-
object Either {
24-
}
23+
//object Either {}
2524
}
2625

2726
object typeclasses {

0 commit comments

Comments
 (0)