Skip to content

Commit 28714e9

Browse files
committed
Disallow context functions as case class elements
Fixes #11859
1 parent 7580ee9 commit 28714e9

File tree

5 files changed

+35
-36
lines changed

5 files changed

+35
-36
lines changed

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

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2151,22 +2151,32 @@ class Typer extends Namer
21512151
val rhsToInline = PrepareInlineable.wrapRHS(ddef, tpt1, rhs1)
21522152
PrepareInlineable.registerInlineInfo(sym, rhsToInline)
21532153

2154-
if (sym.isConstructor && !sym.isPrimaryConstructor) {
2155-
if (sym.targetName != sym.name)
2156-
report.error(em"@targetName annotation may not be used on a constructor", ddef.srcPos)
2157-
2158-
for params <- paramss1; param <- params do
2159-
checkRefsLegal(param, sym.owner, (name, sym) => sym.is(TypeParam), "secondary constructor")
2160-
2161-
def checkThisConstrCall(tree: Tree): Unit = tree match {
2162-
case app: Apply if untpd.isSelfConstrCall(app) =>
2163-
if (sym.span.exists && app.symbol.span.exists && sym.span.start <= app.symbol.span.start)
2164-
report.error("secondary constructor must call a preceding constructor", app.srcPos)
2165-
case Block(call :: _, _) => checkThisConstrCall(call)
2166-
case _ =>
2167-
}
2168-
checkThisConstrCall(rhs1)
2169-
}
2154+
if sym.isConstructor then
2155+
if sym.isPrimaryConstructor then
2156+
if sym.owner.is(Case) then
2157+
for
2158+
params <- paramss1.dropWhile(TypeDefs.unapply(_).isDefined).take(1)
2159+
case param: ValDef <- params
2160+
do
2161+
if defn.isContextFunctionType(param.tpt.tpe) then
2162+
report.error("case class element cannot be a context function", param.srcPos)
2163+
else
2164+
if sym.targetName != sym.name then
2165+
report.error(em"@targetName annotation may not be used on a constructor", ddef.srcPos)
2166+
2167+
for params <- paramss1; param <- params do
2168+
checkRefsLegal(param, sym.owner, (name, sym) => sym.is(TypeParam), "secondary constructor")
2169+
2170+
def checkThisConstrCall(tree: Tree): Unit = tree match
2171+
case app: Apply if untpd.isSelfConstrCall(app) =>
2172+
if (sym.span.exists && app.symbol.span.exists && sym.span.start <= app.symbol.span.start)
2173+
report.error("secondary constructor must call a preceding constructor", app.srcPos)
2174+
case Block(call :: _, _) => checkThisConstrCall(call)
2175+
case _ =>
2176+
2177+
checkThisConstrCall(rhs1)
2178+
end if
2179+
end if
21702180

21712181
if sym.is(Method) && sym.owner.denot.isRefinementClass then
21722182
for annot <- sym.paramSymss.flatten.filter(_.isTerm).flatMap(_.getAnnotation(defn.ImplicitNotFoundAnnot)) do

tests/neg/i11859.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
class I
2+
case class C(x: I ?=> Object) // error: case class element cannot be a context function
3+
4+
type ITO = I ?=> Object
5+
case class D(x: ITO) // error: case class element cannot be a context function
6+
7+
@main def Test =
8+
val c = C(new Object())
9+
assert(c.hashCode == c.hashCode())

tests/pos/case-getters.scala

Lines changed: 0 additions & 8 deletions
This file was deleted.

tests/pos/i11350.scala

Lines changed: 0 additions & 5 deletions
This file was deleted.

tests/pos/i7778.scala

Lines changed: 0 additions & 7 deletions
This file was deleted.

0 commit comments

Comments
 (0)