Skip to content

Fix #5397: Visit local method in Tailrec #5431

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 14, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions compiler/src/dotty/tools/dotc/transform/TailRec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -407,8 +407,11 @@ class TailRec extends MiniPhase {
assert(false, "We should never have gotten inside a pattern")
tree

case _: ValDef | _: DefDef | _: Super | _: This |
_: Literal | _: TypeTree | _: TypeDef | EmptyTree =>
case tree: ValOrDefDef =>
if (isMandatory) noTailTransform(tree.rhs)
tree

case _: Super | _: This | _: Literal | _: TypeTree | _: TypeDef | EmptyTree =>
tree

case Labeled(bind, expr) =>
Expand Down
4 changes: 2 additions & 2 deletions tests/neg-tailcall/t1672b.scala
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ object Test1772B {

// the `liftedTree` local method will prevent a tail call here.
@tailrec
def bar(i : Int) : Int = { // error: TailRec optimisation not applicable
def bar(i : Int) : Int = {
if (i == 0) 0
else 1 + (try {
throw new RuntimeException
} catch {
case _: Throwable => bar(i - 1) // old error: cannot rewrite recursive call
case _: Throwable => bar(i - 1) // error: it is not in tail position
})
}
}
41 changes: 41 additions & 0 deletions tests/neg/i5397.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import annotation.tailrec

object Test {
def foo(x: => Int) = 1
def bar(x: Int => Int) = 1

@tailrec def rec1: Int =
foo(rec1) // error: not in tail position

@tailrec def rec2: Int =
bar(_ => rec2) // error: not in tail position

@tailrec def rec3: Int =
1 + (try ??? catch {
case _: Throwable =>
rec3 // error: not in tail position
})

@tailrec def rec4: Unit = {
def local = rec4 // error: not in tail position
}

@tailrec def rec5: Int = {
val x = {
rec5 // error: not in tail position
1
}
x
}
}

object Test4649 {
@tailrec
def lazyFilter[E](s: Stream[E], p: E => Boolean): Stream[E] = s match {
case h #:: t =>
if (p(h)) h #:: lazyFilter(t, p) // error: not in tail position
else lazyFilter(t, p)
case _ =>
Stream.empty
}
}
2 changes: 0 additions & 2 deletions tests/pos/ErasureAnd.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import scala.annotation.tailrec
trait A { self: B =>
@tailrec
private def foo(arg1: Int, arg2: Int): Int = {
def bar = this.foo(arg1, arg2)
foo(arg1, arg2)
Expand Down
29 changes: 0 additions & 29 deletions tests/pos/tailcall/t4649.scala

This file was deleted.