Skip to content

Commit 431f0fc

Browse files
esarbeallanrenucci
authored andcommitted
Add new style error message for @tailrec (#3312)
1 parent 0061fae commit 431f0fc

File tree

4 files changed

+27
-1
lines changed

4 files changed

+27
-1
lines changed

compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ public enum ErrorMessageID {
104104
EnumCaseDefinitionInNonEnumOwnerID,
105105
ExpectedTypeBoundOrEqualsID,
106106
ClassAndCompanionNameClashID,
107+
TailrecNotApplicableID,
107108
;
108109

109110
public int errorNumber() {

compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1777,6 +1777,7 @@ object messages {
17771777
val explanation =
17781778
hl"""A class marked with the ${"final"} keyword cannot be extended"""
17791779
}
1780+
17801781
case class EnumCaseDefinitionInNonEnumOwner(owner: Symbol)(implicit ctx: Context)
17811782
extends Message(EnumCaseDefinitionInNonEnumOwnerID) {
17821783
val kind = "Syntax"
@@ -1817,4 +1818,12 @@ object messages {
18171818
| - ${other.owner} defines ${other}"""
18181819
}
18191820
}
1821+
1822+
case class TailrecNotApplicable(method: Symbol)(implicit ctx: Context)
1823+
extends Message(TailrecNotApplicableID) {
1824+
val kind = "Syntax"
1825+
val msg = hl"TailRec optimisation not applicable, $method is neither ${"private"} nor ${"final"}."
1826+
val explanation =
1827+
hl"A method annotated ${"@tailrec"} must be declared ${"private"} or ${"final"} so it can't be overridden."
1828+
}
18201829
}

compiler/src/dotty/tools/dotc/transform/TailRec.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import Symbols._
1212
import Types._
1313
import NameKinds.TailLabelName
1414
import TreeTransforms.{MiniPhaseTransform, TransformerInfo}
15+
import reporting.diagnostic.messages.TailrecNotApplicable
1516

1617
/**
1718
* A Tail Rec Transformer
@@ -161,7 +162,7 @@ class TailRec extends MiniPhaseTransform with DenotTransformer with FullParamete
161162
})
162163
}
163164
case d: DefDef if d.symbol.hasAnnotation(defn.TailrecAnnot) || methodsWithInnerAnnots.contains(d.symbol) =>
164-
ctx.error("TailRec optimisation not applicable, method is neither private nor final so can be overridden", sym.pos)
165+
ctx.error(TailrecNotApplicable(sym), sym.pos)
165166
d
166167
case d if d.symbol.hasAnnotation(defn.TailrecAnnot) || methodsWithInnerAnnots.contains(d.symbol) =>
167168
ctx.error("TailRec optimisation not applicable, not a method", sym.pos)

compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,6 +1000,21 @@ class ErrorMessagesTests extends ErrorMessagesTest {
10001000
assertEquals("object Qux", owner.show)
10011001
}
10021002

1003+
@Test def tailrecNotApplicableNeitherPrivateNorFinal =
1004+
checkMessagesAfter("tailrec") {
1005+
"""
1006+
|class Foo {
1007+
| @scala.annotation.tailrec
1008+
| def foo: Unit = foo
1009+
|}
1010+
""".stripMargin
1011+
}.expect { (ictx, messages) =>
1012+
implicit val ctx: Context = ictx
1013+
assertMessageCount(1, messages)
1014+
val TailrecNotApplicable(method) :: Nil = messages
1015+
assertEquals(method.show, "method foo")
1016+
}
1017+
10031018
@Test def expectedTypeBoundOrEquals =
10041019
checkMessagesAfter("frontend") {
10051020
"""object typedef {

0 commit comments

Comments
 (0)