Skip to content

Commit 930ca64

Browse files
committed
Avoid widening derived instances too far
If derived instances are created in companions with the Synthetic flag set then widenImplied will widen too far, and the derived instances will have too low a priority to be selected over a freshly derived instances at the summoning site.
1 parent c02861f commit 930ca64

File tree

2 files changed

+34
-2
lines changed

2 files changed

+34
-2
lines changed

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,14 @@ trait Deriving { this: Typer =>
4949
val instanceName = s"derived$$$clsName".toTermName
5050
if (ctx.denotNamed(instanceName).exists)
5151
ctx.error(i"duplicate typeclass derivation for $clsName", pos)
52-
else
52+
else {
53+
// If we set the Synthetic flag here widenImplied will widen too far and the
54+
// derived instance will have too low a priority to be selected over a freshly
55+
// derived instance at the summoning site.
5356
synthetics +=
54-
ctx.newSymbol(ctx.owner, instanceName, Implied | Synthetic | Method, info, coord = pos.span)
57+
ctx.newSymbol(ctx.owner, instanceName, Implied | Method, info, coord = pos.span)
5558
.entered
59+
}
5660
}
5761

5862
/** Check derived type tree `derived` for the following well-formedness conditions:

tests/run/derived-specificity.scala

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import scala.deriving._
2+
3+
object Test extends App {
4+
case class Foo() derives Bar, Baz
5+
case class Bar[T](id: String)
6+
object Bar {
7+
implicit def barGen[T](implicit m: Mirror.Of[T]): Bar[T] = Bar("Bar.barGen")
8+
def derived[T](implicit m: Mirror.Of[T]): Bar[T] = Bar("Bar.derived")
9+
}
10+
11+
trait Baz[T] {
12+
def id: String
13+
}
14+
object Baz {
15+
def apply[T](id0: String): Baz[T] = new Baz[T] {
16+
def id = id0
17+
}
18+
implicit def bazGen[T](implicit m: Mirror.Of[T]): Baz[T] = Baz("Baz.bazGen")
19+
def derived[T](implicit m: Mirror.Of[T]): Baz[T] = Baz("Baz.derived")
20+
}
21+
22+
val bar = implicitly[Bar[Foo]]
23+
assert(bar.id == "Bar.derived")
24+
25+
val baz = implicitly[Baz[Foo]]
26+
assert(baz.id == "Baz.derived")
27+
}
28+

0 commit comments

Comments
 (0)