Skip to content

Commit 4368847

Browse files
committed
Visit all trees
1 parent a349775 commit 4368847

File tree

3 files changed

+57
-14
lines changed

3 files changed

+57
-14
lines changed

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

+2-14
Original file line numberDiff line numberDiff line change
@@ -277,23 +277,11 @@ class TailRec extends MiniPhase {
277277
def yesTailTransform(tree: Tree)(using Context): Tree =
278278
transform(tree, tailPosition = true)
279279

280-
/** If not in tail position a tree traversal may not be needed.
281-
*
282-
* A recursive call may still be in tail position if within the return
283-
* expression of a labeled block.
284-
* A tree traversal may also be needed to report a failure to transform
285-
* a recursive call of a @tailrec annotated method (i.e. `isMandatory`).
286-
*/
287-
private def isTraversalNeeded =
288-
isMandatory || tailPositionLabeledSyms.size > 0
289-
290280
def noTailTransform(tree: Tree)(using Context): Tree =
291-
if (isTraversalNeeded) transform(tree, tailPosition = false)
292-
else tree
281+
transform(tree, tailPosition = false)
293282

294283
def noTailTransforms[Tr <: Tree](trees: List[Tr])(using Context): List[Tr] =
295-
if (isTraversalNeeded) trees.mapConserve(noTailTransform).asInstanceOf[List[Tr]]
296-
else trees
284+
trees.mapConserve(noTailTransform).asInstanceOf[List[Tr]]
297285

298286
override def transform(tree: Tree)(using Context): Tree = {
299287
/* Rewrite an Apply to be considered for tail call transformation. */

tests/run/tailrec-return.check

+5
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,7 @@
11
6
22
false
3+
true
4+
false
5+
true
6+
Ada Lovelace, Alan Turing
7+
List(9, 10)

tests/run/tailrec-return.scala

+50
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,56 @@ object Test:
1111
if n == 1 then return false
1212
true
1313

14+
@annotation.tailrec
15+
def isEvenApply(n: Int): Boolean =
16+
// Return inside an `Apply.fun`
17+
(
18+
if n != 0 && n != 1 then return isEvenApply(n - 2)
19+
else if n == 1 then return false
20+
else (x: Boolean) => x
21+
)(true)
22+
23+
@annotation.tailrec
24+
def isEvenWhile(n: Int): Boolean =
25+
// Return inside a `WhileDo.cond`
26+
while(
27+
if n != 0 && n != 1 then return isEvenWhile(n - 2)
28+
else if n == 1 then return false
29+
else true
30+
) {}
31+
true
32+
33+
@annotation.tailrec
34+
def isEvenReturn(n: Int): Boolean =
35+
// Return inside a `Return`
36+
return
37+
if n != 0 && n != 1 then return isEvenReturn(n - 2)
38+
else if n == 1 then return false
39+
else true
40+
41+
@annotation.tailrec
42+
def names(l: List[(String, String) | Null], acc: List[String] = Nil): List[String] =
43+
l match
44+
case Nil => acc.reverse
45+
case x :: xs =>
46+
if x == null then return names(xs, acc)
47+
48+
val displayName = x._1 + " " + x._2
49+
names(xs, displayName :: acc)
50+
51+
def nonTail(l: List[Int]): List[Int] =
52+
l match
53+
case Nil => Nil
54+
case x :: xs =>
55+
// The call to nonTail should *not* be eliminated
56+
(x + 1) :: nonTail(xs)
57+
58+
1459
def main(args: Array[String]): Unit =
1560
println(sum(3))
1661
println(isEven(5))
62+
println(isEvenApply(6))
63+
println(isEvenWhile(7))
64+
println(isEvenReturn(8))
65+
println(names(List(("Ada", "Lovelace"), null, ("Alan", "Turing"))).mkString(", "))
66+
println(nonTail(List(8, 9)))

0 commit comments

Comments
 (0)