@@ -429,10 +429,23 @@ class TailRec extends MiniPhase {
429
429
assert(false , " We should never have gotten inside a pattern" )
430
430
tree
431
431
432
- case tree : ValOrDefDef =>
432
+ case tree : ValDef =>
433
433
if (isMandatory) noTailTransform(tree.rhs)
434
434
tree
435
435
436
+ case tree : DefDef =>
437
+ if (isMandatory)
438
+ if (tree.symbol.is(Synthetic ))
439
+ noTailTransform(tree.rhs)
440
+ else
441
+ // We can't tail recurse through nested definitions, so don't want to propagate to child nodes
442
+ // We don't want to fail if there is a call that would recurse (as this would be a non self recurse), so don't
443
+ // want to call noTailTransform
444
+ // We can however warn in this case, as its likely in this situation that someone would expect a tail
445
+ // recursion optimization and enabling this to optimise would be a simple case of inlining the inner method
446
+ new NestedTailRecAlerter (method, tree.symbol).traverse(tree)
447
+ tree
448
+
436
449
case _ : Super | _ : This | _ : Literal | _ : TypeTree | _ : TypeDef | EmptyTree =>
437
450
tree
438
451
@@ -446,14 +459,28 @@ class TailRec extends MiniPhase {
446
459
447
460
case Return (expr, from) =>
448
461
val fromSym = from.symbol
449
- val inTailPosition = ! fromSym.is(Label ) || tailPositionLabeledSyms.contains(fromSym)
462
+ val inTailPosition = tailPositionLabeledSyms.contains(fromSym) // Label returns are only tail if the label is in tail position
463
+ || (fromSym eq method) // Method returns are only tail if we are looking at the original method
450
464
cpy.Return (tree)(transform(expr, inTailPosition), from)
451
465
452
466
case _ =>
453
467
super .transform(tree)
454
468
}
455
469
}
456
470
}
471
+
472
+ class NestedTailRecAlerter (method : Symbol , inner : Symbol ) extends TreeTraverser {
473
+ override def traverse (tree : tpd.Tree )(using Context ): Unit =
474
+ tree match {
475
+ case a : Apply =>
476
+ if (a.fun.symbol eq method) {
477
+ report.warning(new TailrecNestedCall (method, inner), a.srcPos)
478
+ }
479
+ traverseChildren(tree)
480
+ case _ =>
481
+ traverseChildren(tree)
482
+ }
483
+ }
457
484
}
458
485
459
486
object TailRec {
0 commit comments