Skip to content

Commit 6448998

Browse files
authored
Merge pull request #5431 from dotty-staging/fix-5397
Fix #5397: Visit local method in Tailrec
2 parents 755d607 + 4d9d4fa commit 6448998

File tree

5 files changed

+48
-35
lines changed

5 files changed

+48
-35
lines changed

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -407,8 +407,11 @@ class TailRec extends MiniPhase {
407407
assert(false, "We should never have gotten inside a pattern")
408408
tree
409409

410-
case _: ValDef | _: DefDef | _: Super | _: This |
411-
_: Literal | _: TypeTree | _: TypeDef | EmptyTree =>
410+
case tree: ValOrDefDef =>
411+
if (isMandatory) noTailTransform(tree.rhs)
412+
tree
413+
414+
case _: Super | _: This | _: Literal | _: TypeTree | _: TypeDef | EmptyTree =>
412415
tree
413416

414417
case Labeled(bind, expr) =>

tests/neg-tailcall/t1672b.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@ object Test1772B {
4343

4444
// the `liftedTree` local method will prevent a tail call here.
4545
@tailrec
46-
def bar(i : Int) : Int = { // error: TailRec optimisation not applicable
46+
def bar(i : Int) : Int = {
4747
if (i == 0) 0
4848
else 1 + (try {
4949
throw new RuntimeException
5050
} catch {
51-
case _: Throwable => bar(i - 1) // old error: cannot rewrite recursive call
51+
case _: Throwable => bar(i - 1) // error: it is not in tail position
5252
})
5353
}
5454
}

tests/neg/i5397.scala

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import annotation.tailrec
2+
3+
object Test {
4+
def foo(x: => Int) = 1
5+
def bar(x: Int => Int) = 1
6+
7+
@tailrec def rec1: Int =
8+
foo(rec1) // error: not in tail position
9+
10+
@tailrec def rec2: Int =
11+
bar(_ => rec2) // error: not in tail position
12+
13+
@tailrec def rec3: Int =
14+
1 + (try ??? catch {
15+
case _: Throwable =>
16+
rec3 // error: not in tail position
17+
})
18+
19+
@tailrec def rec4: Unit = {
20+
def local = rec4 // error: not in tail position
21+
}
22+
23+
@tailrec def rec5: Int = {
24+
val x = {
25+
rec5 // error: not in tail position
26+
1
27+
}
28+
x
29+
}
30+
}
31+
32+
object Test4649 {
33+
@tailrec
34+
def lazyFilter[E](s: Stream[E], p: E => Boolean): Stream[E] = s match {
35+
case h #:: t =>
36+
if (p(h)) h #:: lazyFilter(t, p) // error: not in tail position
37+
else lazyFilter(t, p)
38+
case _ =>
39+
Stream.empty
40+
}
41+
}

tests/pos/ErasureAnd.scala

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import scala.annotation.tailrec
21
trait A { self: B =>
3-
@tailrec
42
private def foo(arg1: Int, arg2: Int): Int = {
53
def bar = this.foo(arg1, arg2)
64
foo(arg1, arg2)

tests/pos/tailcall/t4649.scala

Lines changed: 0 additions & 29 deletions
This file was deleted.

0 commit comments

Comments
 (0)