@@ -21,14 +21,12 @@ import scala.collection.mutable
21
21
*
22
22
* What it does:
23
23
*
24
- * Finds method calls in tail-position and replaces them with jumps.
25
- * A call is in a tail-position if it is the last instruction to be
26
- * executed in the body of a method. This includes being in
27
- * tail-position of a `return` from a `Labeled` block which is itself
28
- * in tail-position (which is critical for tail-recursive calls in the
29
- * cases of a `match`). To identify tail positions, we recurse over
30
- * the trees that may contain calls in tail-position (trees that can't
31
- * contain such calls are not transformed).
24
+ * Finds method calls in tail-position and replaces them with jumps. A call is
25
+ * in a tail-position if it is the last instruction to be executed in the body
26
+ * of a method. This includes being in tail-position inside a `return`
27
+ * expression. If the `return` targets a `Labeled` block, then the target block
28
+ * must itself be in tail-position (which is critical for tail-recursive calls
29
+ * in the cases of a `match`).
32
30
*
33
31
* When a method contains at least one tail-recursive call, its rhs
34
32
* is wrapped in the following structure:
@@ -49,7 +47,7 @@ import scala.collection.mutable
49
47
* reassigning the local `var`s substituting formal parameters and
50
48
* (b) a `return` from the `tailResult` labeled block, which has the
51
49
* net effect of looping back to the beginning of the method.
52
- * If the receiver is modifed in a recursive call, an additional `var`
50
+ * If the receiver is modified in a recursive call, an additional `var`
53
51
* is used to replace `this`.
54
52
*
55
53
* As a complete example of the transformation, the classical `fact`
@@ -118,7 +116,7 @@ class TailRec extends MiniPhase {
118
116
override def transformDefDef (tree : DefDef )(using Context ): Tree = {
119
117
val method = tree.symbol
120
118
val mandatory = method.hasAnnotation(defn.TailrecAnnot )
121
- def noTailTransform (failureReported : Boolean ) = {
119
+ def transform (failureReported : Boolean ) = {
122
120
// FIXME: want to report this error on `tree.nameSpan`, but
123
121
// because of extension method getting a weird position, it is
124
122
// better to report on method symbol so there's no overlap.
@@ -212,9 +210,9 @@ class TailRec extends MiniPhase {
212
210
)
213
211
)
214
212
}
215
- else noTailTransform (failureReported = transformer.failureReported)
213
+ else transform (failureReported = transformer.failureReported)
216
214
}
217
- else noTailTransform (failureReported = false )
215
+ else transform (failureReported = false )
218
216
}
219
217
220
218
class TailRecElimination (method : Symbol , enclosingClass : ClassSymbol , paramSyms : List [Symbol ], isMandatory : Boolean ) extends TreeMap {
@@ -274,34 +272,13 @@ class TailRec extends MiniPhase {
274
272
finally inTailPosition = saved
275
273
}
276
274
277
- def yesTailTransform (tree : Tree )(using Context ): Tree =
278
- transform(tree, tailPosition = true )
279
-
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
-
290
- def noTailTransform (tree : Tree )(using Context ): Tree =
291
- if (isTraversalNeeded) transform(tree, tailPosition = false )
292
- else tree
293
-
294
- def noTailTransforms [Tr <: Tree ](trees : List [Tr ])(using Context ): List [Tr ] =
295
- if (isTraversalNeeded) trees.mapConserve(noTailTransform).asInstanceOf [List [Tr ]]
296
- else trees
297
-
298
275
override def transform (tree : Tree )(using Context ): Tree = {
299
276
/* Rewrite an Apply to be considered for tail call transformation. */
300
277
def rewriteApply (tree : Apply ): Tree = {
301
- val arguments = noTailTransforms (tree.args)
278
+ val arguments = transform (tree.args)
302
279
303
280
def continue =
304
- cpy.Apply (tree)(noTailTransform (tree.fun), arguments)
281
+ cpy.Apply (tree)(transform (tree.fun), arguments)
305
282
306
283
def fail (reason : String ) = {
307
284
if (isMandatory) {
@@ -344,7 +321,7 @@ class TailRec extends MiniPhase {
344
321
if (prefix eq EmptyTree ) assignParamPairs
345
322
else
346
323
// TODO Opt: also avoid assigning `this` if the prefix is `this.`
347
- (getVarForRewrittenThis(), noTailTransform (prefix)) :: assignParamPairs
324
+ (getVarForRewrittenThis(), transform (prefix)) :: assignParamPairs
348
325
349
326
val assignments = assignThisAndParamPairs match {
350
327
case (lhs, rhs) :: Nil =>
@@ -377,22 +354,22 @@ class TailRec extends MiniPhase {
377
354
case tree @ Apply (fun, args) =>
378
355
val meth = fun.symbol
379
356
if (meth == defn.Boolean_|| || meth == defn.Boolean_&& )
380
- cpy.Apply (tree)(noTailTransform (fun), transform(args))
357
+ cpy.Apply (tree)(transform (fun), transform(args))
381
358
else
382
359
rewriteApply(tree)
383
360
384
361
case tree @ Select (qual, name) =>
385
- cpy.Select (tree)(noTailTransform (qual), name)
362
+ cpy.Select (tree)(transform (qual), name)
386
363
387
364
case tree @ Block (stats, expr) =>
388
365
cpy.Block (tree)(
389
- noTailTransforms (stats),
366
+ transform (stats),
390
367
transform(expr)
391
368
)
392
369
393
370
case tree @ If (cond, thenp, elsep) =>
394
371
cpy.If (tree)(
395
- noTailTransform (cond),
372
+ transform (cond),
396
373
transform(thenp),
397
374
transform(elsep)
398
375
)
@@ -402,33 +379,33 @@ class TailRec extends MiniPhase {
402
379
403
380
case tree @ Match (selector, cases) =>
404
381
cpy.Match (tree)(
405
- noTailTransform (selector),
382
+ transform (selector),
406
383
transformSub(cases)
407
384
)
408
385
409
386
case tree : Try =>
410
- val expr = noTailTransform (tree.expr)
387
+ val expr = transform (tree.expr)
411
388
if (tree.finalizer eq EmptyTree )
412
389
// SI-1672 Catches are in tail position when there is no finalizer
413
390
cpy.Try (tree)(expr, transformSub(tree.cases), EmptyTree )
414
391
else cpy.Try (tree)(
415
392
expr,
416
- noTailTransforms (tree.cases),
417
- noTailTransform (tree.finalizer)
393
+ transformSub (tree.cases),
394
+ transform (tree.finalizer)
418
395
)
419
396
420
397
case tree @ WhileDo (cond, body) =>
421
398
cpy.WhileDo (tree)(
422
- noTailTransform (cond),
423
- noTailTransform (body)
399
+ transform (cond),
400
+ transform (body)
424
401
)
425
402
426
403
case _ : Alternative | _ : Bind =>
427
404
assert(false , " We should never have gotten inside a pattern" )
428
405
tree
429
406
430
407
case tree : ValOrDefDef =>
431
- if (isMandatory) noTailTransform (tree.rhs)
408
+ if (isMandatory) transform (tree.rhs)
432
409
tree
433
410
434
411
case _ : Super | _ : This | _ : Literal | _ : TypeTree | _ : TypeDef | EmptyTree =>
0 commit comments