Skip to content

Commit f43fe1f

Browse files
committed
reject derived with explicit term params
1 parent 7f5e4ce commit f43fe1f

File tree

3 files changed

+49
-2
lines changed

3 files changed

+49
-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/DerivedIssue.check

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
-- Error: tests/neg/7722.scala:2:40 ------------------------------------------------------------------------------------
2+
2 | @scala.annotation.targetName("E") def this() = this(3) // error
3+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4+
| @targetName annotation may not be used on a constructor

tests/neg/i15987/DerivedIssue.scala

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

0 commit comments

Comments
 (0)