From d8bad7adaba9af5083bf8b92454fb50dfb48b925 Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Mon, 18 Apr 2016 22:19:10 +0200 Subject: Tailrec:report error if method containing @tailrec callsite isn't final --- src/dotty/tools/dotc/transform/TailRec.scala | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'src') 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 -- cgit v1.2.3