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/DerivedIssue.check b/tests/neg/i15987/DerivedIssue.check new file mode 100644 index 000000000000..f1254c1c6f57 --- /dev/null +++ b/tests/neg/i15987/DerivedIssue.check @@ -0,0 +1,4 @@ +-- Error: tests/neg/7722.scala:2:40 ------------------------------------------------------------------------------------ +2 | @scala.annotation.targetName("E") def this() = this(3) // error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | @targetName annotation may not be used on a constructor diff --git a/tests/neg/i15987/DerivedIssue.scala b/tests/neg/i15987/DerivedIssue.scala new file mode 100644 index 000000000000..3da8b7765607 --- /dev/null +++ b/tests/neg/i15987/DerivedIssue.scala @@ -0,0 +1,32 @@ +import scala.language.experimental.clauseInterleaving + +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