From f43fe1fdf6acd23e1a751adf958bc5c4b0509239 Mon Sep 17 00:00:00 2001 From: Aleksander Rainko Date: Sun, 4 Aug 2024 17:11:48 +0200 Subject: [PATCH 1/2] reject derived with explicit term params --- .../src/dotty/tools/dotc/typer/Deriving.scala | 15 +++++++-- tests/neg/i15987/DerivedIssue.check | 4 +++ tests/neg/i15987/DerivedIssue.scala | 32 +++++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 tests/neg/i15987/DerivedIssue.check create mode 100644 tests/neg/i15987/DerivedIssue.scala 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 From ffac87d3e9429cbe43e9363cc779c92547534cc1 Mon Sep 17 00:00:00 2001 From: Aleksander Rainko Date: Mon, 5 Aug 2024 21:13:40 +0200 Subject: [PATCH 2/2] add a test for the new error message --- tests/neg/i15987.check | 5 +++++ tests/neg/{i15987/DerivedIssue.scala => i15987.scala} | 2 -- tests/neg/i15987/DerivedIssue.check | 4 ---- 3 files changed, 5 insertions(+), 6 deletions(-) create mode 100644 tests/neg/i15987.check rename tests/neg/{i15987/DerivedIssue.scala => i15987.scala} (93%) delete mode 100644 tests/neg/i15987/DerivedIssue.check 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/DerivedIssue.scala b/tests/neg/i15987.scala similarity index 93% rename from tests/neg/i15987/DerivedIssue.scala rename to tests/neg/i15987.scala index 3da8b7765607..743f5f7ccda0 100644 --- a/tests/neg/i15987/DerivedIssue.scala +++ b/tests/neg/i15987.scala @@ -1,5 +1,3 @@ -import scala.language.experimental.clauseInterleaving - trait ShowWithExplicit[A] object ShowWithExplicit: diff --git a/tests/neg/i15987/DerivedIssue.check b/tests/neg/i15987/DerivedIssue.check deleted file mode 100644 index f1254c1c6f57..000000000000 --- a/tests/neg/i15987/DerivedIssue.check +++ /dev/null @@ -1,4 +0,0 @@ --- 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