diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/TailCalls.scala | 8 | ||||
-rw-r--r-- | test/files/neg/t6526.check | 16 | ||||
-rw-r--r-- | test/files/neg/t6526.scala | 41 |
3 files changed, 62 insertions, 3 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala index 0ad6d6c677..c8ea43269a 100644 --- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala +++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala @@ -208,7 +208,7 @@ abstract class TailCalls extends Transform { debuglog("Cannot rewrite recursive call at: " + fun.pos + " because: " + reason) ctx.failReason = reason - treeCopy.Apply(tree, target, transformArgs) + treeCopy.Apply(tree, noTailTransform(target), transformArgs) } /** Position of failure is that of the tree being considered. */ @@ -220,7 +220,7 @@ abstract class TailCalls extends Transform { debuglog("Rewriting tail recursive call: " + fun.pos.lineContent.trim) accessed += ctx.label - typedPos(fun.pos)(Apply(Ident(ctx.label), recv :: transformArgs)) + typedPos(fun.pos)(Apply(Ident(ctx.label), noTailTransform(recv) :: transformArgs)) } if (!ctx.isEligible) fail("it is neither private nor final so can be overridden") @@ -361,7 +361,9 @@ abstract class TailCalls extends Transform { case Alternative(_) | Star(_) | Bind(_, _) => sys.error("We should've never gotten inside a pattern") - case EmptyTree | Super(_, _) | This(_) | Select(_, _) | Ident(_) | Literal(_) | Function(_, _) | TypeTree() => + case Select(qual, name) => + treeCopy.Select(tree, noTailTransform(qual), name) + case EmptyTree | Super(_, _) | This(_) | Ident(_) | Literal(_) | Function(_, _) | TypeTree() => tree case _ => super.transform(tree) diff --git a/test/files/neg/t6526.check b/test/files/neg/t6526.check new file mode 100644 index 0000000000..606c18c301 --- /dev/null +++ b/test/files/neg/t6526.check @@ -0,0 +1,16 @@ +t6526.scala:8: error: could not optimize @tailrec annotated method inner: it contains a recursive call not in tail position + @tailrec def inner(i: Int): Int = 1 + inner(i) + ^ +t6526.scala:14: error: could not optimize @tailrec annotated method inner: it contains a recursive call not in tail position + @tailrec def inner(i: Int): Int = 1 + inner(i) + ^ +t6526.scala:20: error: could not optimize @tailrec annotated method inner: it contains a recursive call not in tail position + @tailrec def inner(i: Int): Int = 1 + inner(i) + ^ +t6526.scala:30: error: could not optimize @tailrec annotated method inner: it contains a recursive call not in tail position + @tailrec def inner(i: Int): Int = 1 + inner(i) + ^ +t6526.scala:39: error: could not optimize @tailrec annotated method inner: it contains a recursive call not in tail position + def inner(i: Int): Int = 1 + inner(i) + ^ +5 errors found diff --git a/test/files/neg/t6526.scala b/test/files/neg/t6526.scala new file mode 100644 index 0000000000..0bc249aa98 --- /dev/null +++ b/test/files/neg/t6526.scala @@ -0,0 +1,41 @@ +import scala.annotation.tailrec + +class TailRec { + def bar(f: => Any) = "" + + // transform the qualifier of a Select + bar { + @tailrec def inner(i: Int): Int = 1 + inner(i) + inner(0) + }.length + + // transform the body of a function + () => { + @tailrec def inner(i: Int): Int = 1 + inner(i) + inner(0) + } + + // transform the qualifier of a Select + { + @tailrec def inner(i: Int): Int = 1 + inner(i) + inner(0) + "" + }.length + + // The receiver of a tail recursive call must itself be transformed + object X { + @tailrec // okay, all other annotated methods should fail. + def foo: Any = { + { + @tailrec def inner(i: Int): Int = 1 + inner(i) + inner(0) + this + }.foo + } + } + + Some(new AnyRef) map { phooie => + @tailrec + def inner(i: Int): Int = 1 + inner(i) + } getOrElse 42 +} |