@@ -245,11 +245,23 @@ class TailRec extends MiniPhase {
245
245
def yesTailTransform (tree : Tree )(implicit ctx : Context ): Tree =
246
246
transform(tree, tailPosition = true )
247
247
248
+ /** If not in tail position a tree traversal may not be needed.
249
+ *
250
+ * A recursive call may still be in tail position if within the return
251
+ * expression of a labelled block.
252
+ * A tree traversal may also be needed to report a failure to transform
253
+ * a recursive call of a @tailrec annotated method (i.e. `isMandatory`).
254
+ */
255
+ private def isTraversalNeeded =
256
+ isMandatory || tailPositionLabeledSyms.nonEmpty
257
+
248
258
def noTailTransform (tree : Tree )(implicit ctx : Context ): Tree =
249
- transform(tree, tailPosition = false )
259
+ if (isTraversalNeeded) transform(tree, tailPosition = false )
260
+ else tree
250
261
251
262
def noTailTransforms [Tr <: Tree ](trees : List [Tr ])(implicit ctx : Context ): List [Tr ] =
252
- trees.mapConserve(noTailTransform).asInstanceOf [List [Tr ]]
263
+ if (isTraversalNeeded) trees.mapConserve(noTailTransform).asInstanceOf [List [Tr ]]
264
+ else trees
253
265
254
266
override def transform (tree : Tree )(implicit ctx : Context ): Tree = {
255
267
/* Rewrite an Apply to be considered for tail call transformation. */
@@ -328,24 +340,6 @@ class TailRec extends MiniPhase {
328
340
continue
329
341
}
330
342
331
- def rewriteTry (tree : Try ): Try = {
332
- if (tree.finalizer eq EmptyTree ) {
333
- // SI-1672 Catches are in tail position when there is no finalizer
334
- cpy.Try (tree)(
335
- noTailTransform(tree.expr),
336
- transformSub(tree.cases),
337
- EmptyTree
338
- )
339
- }
340
- else {
341
- cpy.Try (tree)(
342
- noTailTransform(tree.expr),
343
- noTailTransforms(tree.cases),
344
- noTailTransform(tree.finalizer)
345
- )
346
- }
347
- }
348
-
349
343
tree match {
350
344
case tree @ Apply (fun, args) =>
351
345
val meth = fun.symbol
@@ -380,13 +374,22 @@ class TailRec extends MiniPhase {
380
374
)
381
375
382
376
case tree : Try =>
383
- rewriteTry(tree)
377
+ val expr = noTailTransform(tree.expr)
378
+ if (tree.finalizer eq EmptyTree ) {
379
+ // SI-1672 Catches are in tail position when there is no finalizer
380
+ cpy.Try (tree)(expr, transformSub(tree.cases), EmptyTree )
381
+ }
382
+ else cpy.Try (tree)(
383
+ expr,
384
+ noTailTransforms(tree.cases),
385
+ noTailTransform(tree.finalizer)
386
+ )
384
387
385
388
case tree @ WhileDo (cond, body) =>
386
- // we traverse the body and the condition for the purpose of reporting errors
387
- noTailTransform(cond)
388
- noTailTransform(body)
389
- tree
389
+ cpy. WhileDo (tree)(
390
+ noTailTransform(cond),
391
+ noTailTransform(body)
392
+ )
390
393
391
394
case _ : Alternative | _ : Bind =>
392
395
assert(false , " We should never have gotten inside a pattern" )
@@ -399,7 +402,9 @@ class TailRec extends MiniPhase {
399
402
case Labeled (bind, expr) =>
400
403
if (inTailPosition)
401
404
tailPositionLabeledSyms += bind.symbol
402
- cpy.Labeled (tree)(bind, transform(expr))
405
+ try cpy.Labeled (tree)(bind, transform(expr))
406
+ finally if (inTailPosition)
407
+ tailPositionLabeledSyms -= bind.symbol
403
408
404
409
case Return (expr, from) =>
405
410
val fromSym = from.symbol
0 commit comments