Skip to content

Recursion limit exceeded #16061

Open
Open
@TimWSpence

Description

@TimWSpence

Compiler version

3.2.0

Minimized code

import scala.annotation.tailrec

enum Free[+F[_], A]:
  case Return(a: A) extends Free[Nothing, A]
  case Suspend(s: F[A])
  case FlatMap[F[_], X, A](s: Free[F, X], f: X => Free[F, A]) extends Free[F, A]

  def flatMap[F2[x] >: F[x], B](f: A => Free[F2, B]): Free[F2, B] =
    FlatMap(this, f)

  def covary[F2[x] >: F[x]]: Free[F2, A] = this

  @tailrec
  private def step: Free[F, A] = this match
    case FlatMap(Return(a), f) => f(a).step
    case FlatMap(FlatMap(y, f), g) =>
      y.flatMap(a => f(a).flatMap(g)).step
    case x => x

Output

private def step: Free[F, A] = this match
[error]    |                                      ^
[error]    |Recursion limit exceeded.
[error]    |Maybe there is an illegal cyclic reference?
[error]    |If that's not the case, you could also try to increase the stacksize using the -Xss JVM option.
[error]    |A recurring operation is (inner to outer):
[error]    |
[error]    |  traversing for avoiding local references F$3
[error]    |  traversing for avoiding local references F$2
[error]    |  traversing for avoiding local references F$3
[error]    |  traversing for avoiding local references F$2
[error]    |  traversing for avoiding local references F$3
[error]    |  traversing for avoiding local references F$2
[error]    |  traversing for avoiding local references F$3
[error]    |  traversing for avoiding local references F$2
[error]    |  traversing for avoiding local references F$3
[error]    |  traversing for avoiding local references F$2
[error]    |  ...
[error]    |
[error]    |  traversing for avoiding local references F$3
[error]    |  traversing for avoiding local references F$2
[error]    |  traversing for avoiding local references F$3
[error]    |  traversing for avoiding local references F$2
[error]    |  traversing for avoiding local references F$3
[error]    |  traversing for avoiding local references F$2
[error]    |  traversing for avoiding local references F$3
[error]    |  traversing for avoiding local references F$2
[error]    |  traversing for avoiding local references io.github.timwspence.fpinscala.free.Free[F$2, A]
[error]    |  traversing for avoiding local references (io.github.timwspence.fpinscala.free.Free[F$2, A]#step :
[error]    |  => io.github.timwspence.fpinscala.free.Free[F$2, A]
[error]    |)
[error] one error found
[error] one error found
[error] (coreJVM / Compile / compileIncremental) Compilation failed

Expectation

It should compile or at least fail gracefully. Adding a covary call to step fixes it:

  @tailrec
  private def step: Free[F, A] = this match
    case FlatMap(Return(a), f) => f(a).step
    case FlatMap(FlatMap(y, f), g) =>
      y.flatMap(a => f(a).covary[F].flatMap(g)).step
    case x => x

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions