aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Petrashko <dmitry.petrashko@gmail.com>2016-04-18 22:19:10 +0200
committerDmitry Petrashko <dmitry.petrashko@gmail.com>2016-04-18 22:19:10 +0200
commitd8bad7adaba9af5083bf8b92454fb50dfb48b925 (patch)
treebeec6f991d88ee545a468de3245abb10923cc22f
parentca47bea3eed87eaa6005161c831805cd68fd6e59 (diff)
downloaddotty-d8bad7adaba9af5083bf8b92454fb50dfb48b925.tar.gz
dotty-d8bad7adaba9af5083bf8b92454fb50dfb48b925.tar.bz2
dotty-d8bad7adaba9af5083bf8b92454fb50dfb48b925.zip
Tailrec:report error if method containing @tailrec callsite isn't final
-rw-r--r--src/dotty/tools/dotc/transform/TailRec.scala18
1 files changed, 16 insertions, 2 deletions
diff --git a/src/dotty/tools/dotc/transform/TailRec.scala b/src/dotty/tools/dotc/transform/TailRec.scala
index 427884e14..efa0633d8 100644
--- a/src/dotty/tools/dotc/transform/TailRec.scala
+++ b/src/dotty/tools/dotc/transform/TailRec.scala
@@ -73,6 +73,20 @@ class TailRec extends MiniPhaseTransform with DenotTransformer with FullParamete
final val labelPrefix = "tailLabel"
final val labelFlags = Flags.Synthetic | Flags.Label
+ /** Symbols of methods that have @tailrec annotatios inside */
+ private val methodsWithInnerAnnots = new collection.mutable.HashSet[Symbol]()
+
+ override def transformUnit(tree: Tree)(implicit ctx: Context, info: TransformerInfo): Tree = {
+ methodsWithInnerAnnots.clear()
+ tree
+ }
+
+ override def transformTyped(tree: Typed)(implicit ctx: Context, info: TransformerInfo): Tree = {
+ if (tree.tpt.tpe.hasAnnotation(defn.TailrecAnnot))
+ methodsWithInnerAnnots += ctx.owner.enclosingMethod
+ tree
+ }
+
private def mkLabel(method: Symbol, abstractOverClass: Boolean)(implicit c: Context): TermSymbol = {
val name = c.freshName(labelPrefix)
@@ -137,10 +151,10 @@ class TailRec extends MiniPhaseTransform with DenotTransformer with FullParamete
}
})
}
- case d: DefDef if d.symbol.hasAnnotation(defn.TailrecAnnot) =>
+ case d: DefDef if d.symbol.hasAnnotation(defn.TailrecAnnot) || methodsWithInnerAnnots.contains(d.symbol) =>
ctx.error("TailRec optimisation not applicable, method is neither private nor final so can be overridden", d.pos)
d
- case d if d.symbol.hasAnnotation(defn.TailrecAnnot) =>
+ case d if d.symbol.hasAnnotation(defn.TailrecAnnot) || methodsWithInnerAnnots.contains(d.symbol) =>
ctx.error("TailRec optimisation not applicable, not a method", d.pos)
d
case _ => tree