Skip to content

Compiler hang with covariant type constructor in GADT #14287

Closed
@mpilquist

Description

@mpilquist

Compiler version

3.1.1-RC2

Minimized code

// using scala 3.1.1-RC2

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

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

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

Output

Compilation hangs when using scala-cli. In a larger code base, I've seen crashes with stacks like the following, though I haven't reproduced the crash in a standalone program. The hang & crash are both related to making F covariant in the definition of Free.

In the example above, changing the left-associated flatMap case to case FlatMap(FlatMap(fx, f), g) => ??? fixes the issue.

[error] dotty.tools.dotc.core.TypeOps$.dotty$tools$dotc$core$TypeOps$$anon$1$$_$op$proxy5$1(TypeOps.scala:451)
[error] dotty.tools.dotc.core.TypeOps$$anon$1.apply(TypeOps.scala:451)
[error] dotty.tools.dotc.core.TypeOps$$anon$1.apply(TypeOps.scala:451)
[error] dotty.tools.dotc.core.TypeOps$.dotty$tools$dotc$core$TypeOps$$anon$1$$_$op$proxy5$1(TypeOps.scala:451)
[error] dotty.tools.dotc.core.TypeOps$$anon$1.apply(TypeOps.scala:451)
[error] dotty.tools.dotc.core.TypeOps$$anon$1.apply(TypeOps.scala:451)
[error] dotty.tools.dotc.core.TypeOps$.dotty$tools$dotc$core$TypeOps$$anon$1$$_$op$proxy5$1(TypeOps.scala:451)
[error] dotty.tools.dotc.core.TypeOps$$anon$1.apply(TypeOps.scala:451)
[error] dotty.tools.dotc.core.TypeOps$$anon$1.apply(TypeOps.scala:451)
[error] dotty.tools.dotc.core.TypeOps$.dotty$tools$dotc$core$TypeOps$$anon$1$$_$op$proxy5$1(TypeOps.scala:451)

Another workaround is explicitly providing types to the flatMap calls in the problematic expression:

    case FlatMap(FlatMap(fx, f), g) =>
      fx.flatMap[F, A](x => f(x).flatMap[F, A](g)).step

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions