Skip to content

3.3.0-RC2 regression: recursion limit exceeded on GADT pattern match #16777

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

Closed
neko-kai opened this issue Jan 27, 2023 · 0 comments · Fixed by #15683
Closed

3.3.0-RC2 regression: recursion limit exceeded on GADT pattern match #16777

neko-kai opened this issue Jan 27, 2023 · 0 comments · Fixed by #15683
Assignees
Milestone

Comments

@neko-kai
Copy link
Contributor

neko-kai commented Jan 27, 2023

Compiler version

3.3.0-RC1, 3.3.0-RC2, 3.3.1-RC1-bin-20230126-f545d10-NIGHTLY

Did not happen on 3.2.2

Minimized code

3.3.0-RC2: https://scastie.scala-lang.org/xmkJPcdSTRKnYucH905AoQ (Same code works on 3.2.2)

// scalacOptions += "-Ykind-projector:underscores"

sealed abstract class Free[+S[_, _], +E, +A] {
  @inline final def flatMap[S1[e, a] >: S[e, a], B, E1 >: E](fun: A => Free[S1, E1, B]): Free[S1, E1, B] = Free.FlatMapped[S1, E, E1, A, B](this, fun)
  @inline final def map[B](fun: A => B): Free[S, E, B] = flatMap(a => Free.pure[S, B](fun(a)))
  @inline final def as[B](as: => B): Free[S, E, B] = map(_ => as)
  @inline final def *>[S1[e, a] >: S[e, a], B, E1 >: E](sc: Free[S1, E1, B]): Free[S1, E1, B] = flatMap(_ => sc)
  @inline final def <*[S1[e, a] >: S[e, a], B, E1 >: E](sc: Free[S1, E1, B]): Free[S1, E1, A] = flatMap(r => sc.as(r))

  @inline final def void: Free[S, E, Unit] = map(_ => ())

  // FIXME: Scala 3.1.4 bug: false unexhaustive match warning
  /// @nowarn("msg=pattern case: Free.FlatMapped")
  @inline final def foldMap[S1[e, a] >: S[e, a], G[+_, +_]](transform: S1 ~>> G)(implicit G: Monad2[G]): G[E, A] = {
    this match {
      case Free.Pure(a) => G.pure(a)
      case Free.Suspend(a) => transform.apply(a)
      case Free.FlatMapped(sub, cont) =>
        sub match {
          case Free.FlatMapped(sub2, cont2) => sub2.flatMap(a => cont2(a).flatMap(cont)).foldMap(transform)
          case another => G.flatMap(another.foldMap(transform))(cont(_).foldMap(transform))
        }
    }
  }
}

trait ~>>[-F[_, _], +G[_, _]] {
  def apply[E, A](f: F[E, A]): G[E, A]
}

object Free {
  @inline def pure[S[_, _], A](a: A): Free[S, Nothing, A] = Pure(a)
  @inline def lift[S[_, _], E, A](s: S[E, A]): Free[S, E, A] = Suspend(s)

  final case class Pure[S[_, _], A](a: A) extends Free[S, Nothing, A] {
    override def toString: String = s"Pure:[$a]"
  }
  final case class Suspend[S[_, _], E, A](a: S[E, A]) extends Free[S, E, A] {
    override def toString: String = s"Suspend:[$a]"
  }
  final case class FlatMapped[S[_, _], E, E1 >: E, A, B](sub: Free[S, E, A], cont: A => Free[S, E1, B]) extends Free[S, E1, B] {
    override def toString: String = s"FlatMapped:[sub=$sub]"
  }
}

type Monad2[F[+_, +_]] = Monad3[λ[(`-R`, `+E`, `+A`) => F[E, A]]]

trait Monad3[F[-_, +_, +_]] {
  def flatMap[R, E, A, B](r: F[R, E, A])(f: A => F[R, E, B]): F[R, E, B]
  def flatten[R, E, A](r: F[R, E, F[R, E, A]]): F[R, E, A] = flatMap(r)(identity)
  def pure[A](a: A): F[Any, Nothing, A]
}

Output

Recursion limit exceeded.
Maybe there is an illegal cyclic reference?
If that's not the case, you could also try to increase the stacksize using the -Xss JVM option.
For the unprocessed stack trace, compile with -Yno-decode-stacktraces.
A recurring operation is (inner to outer):

  traversing for avoiding local references E$2
  traversing for avoiding local references E1$1
  traversing for avoiding local references E$2
  traversing for avoiding local references E1$1
  traversing for avoiding local references E$2
  traversing for avoiding local references E1$1
  traversing for avoiding local references E$2
  traversing for avoiding local references E1$1
  traversing for avoiding local references E$2
  traversing for avoiding local references E1$1
  ...

  traversing for avoiding local references E1$1
  traversing for avoiding local references E$2
  traversing for avoiding local references E1$1
  traversing for avoiding local references E$2
  traversing for avoiding local references E1$1
  traversing for avoiding local references E$2
  traversing for avoiding local references E1$1
  traversing for avoiding local references E$2
  traversing for avoiding local references E1$1
  traversing for avoiding local references G[E1$1, B$1]

Expectation

Expected to compile, as on 3.2.2.

Workaround not found yet.

@neko-kai neko-kai added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Jan 27, 2023
@dwijnand dwijnand removed the stat:needs triage Every issue needs to have an "area" and "itype" label label Jan 27, 2023
@dwijnand dwijnand self-assigned this Jan 27, 2023
@dwijnand dwijnand linked a pull request Jan 27, 2023 that will close this issue
@Kordyjan Kordyjan modified the milestones: 3.3.1, 3.3.0 Aug 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants