ghostdogpr / caliban

Functional GraphQL library for Scala
https://ghostdogpr.github.io/caliban/
Apache License 2.0
947 stars 248 forks source link

Mutually referenced argument types cause runtime stack overflow #858

Closed tmilner closed 3 years ago

tmilner commented 3 years ago

I recently raised, then closed, an issue about a schema that never finished compiling. I have narrowed it down to a lack of ArgBuilder implicits and upon defining these the compile completes pretty quickly.

However, now that it compile it does not run. In fact at runtime it fails with a stack overflow as soon as you try and run a query.

The minimal schema:

  case class EntityArgs1(id: ID, args2: EntityArgs2)
  implicit lazy val schema1: Schema[Any, EntityArgs1] = Schema.gen[EntityArgs1]
  implicit lazy val argBuilder: ArgBuilder[EntityArgs1] = ArgBuilder.gen[EntityArgs1]

  case class EntityArgs2(id: ID, args2: EntityArgs1)
  implicit lazy val schema2: Schema[Any, EntityArgs2] = Schema.gen[EntityArgs2]
  implicit lazy val argBuilder2: ArgBuilder[EntityArgs2] = ArgBuilder.gen[EntityArgs2]

  case class Entity(
    id: ID,
    trackingEvents: EntityArgs1 => Option[ID],
  )

  implicit val autoEntitySchema: Schema[Any, Entity] = Schema.gen[Entity]

  case class Query(
    entity: ID => IO[Option[Entity]]
  )

Here is a running example - https://scastie.scala-lang.org/3IXJ7kVITASEcpotUM59gg

Is this is known issue? or does anyone know how to work around this? If I remove the implicit I had issues with it never finishing the compile.

ghostdogpr commented 3 years ago

I reported it to magnolia but it couldn't be fixed: https://github.com/propensive/magnolia/issues/190

There is a workaround in this case though: make only one of them lazy. Like this: https://scastie.scala-lang.org/LGeOoMIUSoKybUrp7J4JOg It might be trickier to apply in a real life use case unfortunately.

tmilner commented 3 years ago

Ouch, OK thanks. Good to know.

I guess I should just close this then?

ghostdogpr commented 3 years ago

Yeah, unfortunately there isn't much I can do about it on Caliban side. Hopefully the workaround will work for you. I'm also hoping this problem will be gone in Scala 3 since derivation will use Scala core features and should be less hacky.