diff --git a/compiler/src/dotty/tools/dotc/typer/Deriving.scala b/compiler/src/dotty/tools/dotc/typer/Deriving.scala index 619dfcf4d7cb..60148319a61c 100644 --- a/compiler/src/dotty/tools/dotc/typer/Deriving.scala +++ b/compiler/src/dotty/tools/dotc/typer/Deriving.scala @@ -292,10 +292,21 @@ trait Deriving { val companion = companionRef(resultType) val module = untpd.ref(companion).withSpan(sym.span) val rhs = untpd.Select(module, nme.derived) - if companion.termSymbol.exists then typed(rhs, resultType) - else errorTree(rhs, em"$resultType cannot be derived since ${resultType.typeSymbol} has no companion object") + val derivedMember = companion.member(nme.derived) + + if !companion.termSymbol.exists then + errorTree(rhs, em"$resultType cannot be derived since ${resultType.typeSymbol} has no companion object") + else if hasExplicitParams(derivedMember.symbol) then + errorTree(rhs, em"""derived instance $resultType failed to generate: + |method `derived` from object ${module} takes explicit term parameters""") + else + typed(rhs, resultType) end typeclassInstance + // checks whether any of the params of 'sym' is explicit + def hasExplicitParams(sym: Symbol) = + !sym.paramSymss.flatten.forall(sym => sym.isType || sym.is(Flags.Given) || sym.is(Flags.Implicit)) + def syntheticDef(sym: Symbol): Tree = inContext(ctx.fresh.setOwner(sym).setNewScope) { if sym.is(Method) then tpd.DefDef(sym.asTerm, typeclassInstance(sym)) else tpd.ValDef(sym.asTerm, typeclassInstance(sym)(Nil)) diff --git a/tests/neg/i15987.check b/tests/neg/i15987.check new file mode 100644 index 000000000000..b62c8cac160b --- /dev/null +++ b/tests/neg/i15987.check @@ -0,0 +1,5 @@ +-- Error: tests/neg/i15987.scala:26:40 --------------------------------------------------------------------------------- +26 |case class Person(name: String) derives ShowWithExplicit, // error + | ^ + | derived instance ShowWithExplicit[Person] failed to generate: + | method `derived` from object ShowWithExplicit takes explicit term parameters diff --git a/tests/neg/i15987.scala b/tests/neg/i15987.scala new file mode 100644 index 000000000000..743f5f7ccda0 --- /dev/null +++ b/tests/neg/i15987.scala @@ -0,0 +1,30 @@ +trait ShowWithExplicit[A] + +object ShowWithExplicit: + def derived[A, B](explicit: String)(using DummyImplicit)(implicit dummy: DummyImplicit): ShowWithExplicit[A] = ??? + +trait ShowUsingAndImplicit[A] + +object ShowUsingAndImplicit: + def derived[A, B](using DummyImplicit)(implicit dummy: DummyImplicit): ShowUsingAndImplicit[A] = ??? + +trait ShowUsing[A] + +object ShowUsing: + def derived[A](using DummyImplicit): ShowUsing[A] = ??? + +trait ShowImplicit[A] + +object ShowImplicit: + def derived[A](implicit ev: DummyImplicit): ShowImplicit[A] = ??? + +trait ShowContra[-A] + +object ShowContra: + val derived: ShowContra[Any] = ??? + +case class Person(name: String) derives ShowWithExplicit, // error + ShowUsingAndImplicit, + ShowUsing, + ShowImplicit, + ShowContra