Skip to content

Commit 78561ce

Browse files
authored
[Issue 15987] Nicer error message in case a derived method has an explicit term param (#21332)
2 parents 5730f91 + ffac87d commit 78561ce

File tree

3 files changed

+48
-2
lines changed

3 files changed

+48
-2
lines changed

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

+13-2
Original file line numberDiff line numberDiff line change
@@ -292,10 +292,21 @@ trait Deriving {
292292
val companion = companionRef(resultType)
293293
val module = untpd.ref(companion).withSpan(sym.span)
294294
val rhs = untpd.Select(module, nme.derived)
295-
if companion.termSymbol.exists then typed(rhs, resultType)
296-
else errorTree(rhs, em"$resultType cannot be derived since ${resultType.typeSymbol} has no companion object")
295+
val derivedMember = companion.member(nme.derived)
296+
297+
if !companion.termSymbol.exists then
298+
errorTree(rhs, em"$resultType cannot be derived since ${resultType.typeSymbol} has no companion object")
299+
else if hasExplicitParams(derivedMember.symbol) then
300+
errorTree(rhs, em"""derived instance $resultType failed to generate:
301+
|method `derived` from object ${module} takes explicit term parameters""")
302+
else
303+
typed(rhs, resultType)
297304
end typeclassInstance
298305

306+
// checks whether any of the params of 'sym' is explicit
307+
def hasExplicitParams(sym: Symbol) =
308+
!sym.paramSymss.flatten.forall(sym => sym.isType || sym.is(Flags.Given) || sym.is(Flags.Implicit))
309+
299310
def syntheticDef(sym: Symbol): Tree = inContext(ctx.fresh.setOwner(sym).setNewScope) {
300311
if sym.is(Method) then tpd.DefDef(sym.asTerm, typeclassInstance(sym))
301312
else tpd.ValDef(sym.asTerm, typeclassInstance(sym)(Nil))

tests/neg/i15987.check

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-- Error: tests/neg/i15987.scala:26:40 ---------------------------------------------------------------------------------
2+
26 |case class Person(name: String) derives ShowWithExplicit, // error
3+
| ^
4+
| derived instance ShowWithExplicit[Person] failed to generate:
5+
| method `derived` from object ShowWithExplicit takes explicit term parameters

tests/neg/i15987.scala

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
trait ShowWithExplicit[A]
2+
3+
object ShowWithExplicit:
4+
def derived[A, B](explicit: String)(using DummyImplicit)(implicit dummy: DummyImplicit): ShowWithExplicit[A] = ???
5+
6+
trait ShowUsingAndImplicit[A]
7+
8+
object ShowUsingAndImplicit:
9+
def derived[A, B](using DummyImplicit)(implicit dummy: DummyImplicit): ShowUsingAndImplicit[A] = ???
10+
11+
trait ShowUsing[A]
12+
13+
object ShowUsing:
14+
def derived[A](using DummyImplicit): ShowUsing[A] = ???
15+
16+
trait ShowImplicit[A]
17+
18+
object ShowImplicit:
19+
def derived[A](implicit ev: DummyImplicit): ShowImplicit[A] = ???
20+
21+
trait ShowContra[-A]
22+
23+
object ShowContra:
24+
val derived: ShowContra[Any] = ???
25+
26+
case class Person(name: String) derives ShowWithExplicit, // error
27+
ShowUsingAndImplicit,
28+
ShowUsing,
29+
ShowImplicit,
30+
ShowContra

0 commit comments

Comments
 (0)