Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport "Preventing compilation of a @tailrec method when it does not rewrite, but an inner method does" to LTS #21142

Closed
wants to merge 1 commit into from

Conversation

WojciechMazur
Copy link
Contributor

Backports #20143 to the LTS branch.

PR submitted by the release tooling.
[skip ci]

…ontain non-tail recursive calls.

Code will now compile where a child def calls the parent def in a non-tail position (with the warning).
Code will no longer compile if all calls to a @tailrec method are in named child methods (as these do not tail recurse).

[Cherry-picked 01ada74]
@WojciechMazur
Copy link
Contributor Author

WojciechMazur commented Jul 10, 2024

This change leads to a failure in Open Community Build for sageserpent-open/kineticmerge Open CB logs, but it's an expected one. The failing code can be minimized to:

import scala.annotation.tailrec

@tailrec private def outer(i: Int): String =
  @tailrec def inner(i: Int): String =
    if i == 0 then  inner(i + 1)
    else if i == 1 then  outer(i + 1)
    else if i == 2 then outer(0)
    else "fallback"
  inner(i)

@main def Test = outer(0)

Previously it compiled but failed at runtime, now it fails at compile-time with

Compiling project (Scala 3.3.4-RC1-bin-SNAPSHOT, JVM (17))
[warn] ./test.scala:6:26
[warn] The tail recursive def outer contains a recursive call inside the non-inlined inner def inner
[warn]     else if i == 1 then  outer(i + 1)
[warn]                          ^^^^^^^^^^^^
[warn] ./test.scala:7:10
[warn] The tail recursive def outer contains a recursive call inside the non-inlined inner def inner
[warn]     else outer(0)
[warn]          ^^^^^^^^
[error] ./test.scala:3:22
[error] TailRec optimisation not applicable, method outer contains no recursive calls
[error] @tailrec private def outer(i: Int): String =
[error]      

The previous behaviour was a bug that is now going to be fixed. It gave a false guarantee of safety that could have led to unexpected StackOverflowError. However, it breaks the source compatibility guarantees thus needs to be decided by the core team on either this change should be included.

@WojciechMazur WojciechMazur marked this pull request as draft July 10, 2024 12:16
Base automatically changed from lts-20558 to lts-3.3 July 10, 2024 14:23
@WojciechMazur
Copy link
Contributor Author

It was decided in the core meeting to not backport this change to the LTS

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant