Recurrent args hang in compile time or runtime
pawelprazak opened this issue · 1 comments
pawelprazak commented
This test replicated a problem detected in JsonSchemaPropsArgs
(k8s)
class RecurrentArgsTest extends munit.FunSuite with ValueAssertions:
case class Recurrent (
properties: Option[Recurrent]
)
object Recurrent:
given encoder(using besom.types.Context): besom.types.Encoder[Recurrent] =
besom.internal.Encoder.derived[Recurrent]
test("encode recurrent type") {
given Context = DummyContext().unsafeRunSync()
val e = summon[Encoder[Recurrent]]
val (_, encoded) = e.encode(Recurrent(Some(Recurrent(Some(Recurrent(Some(Recurrent(None)))))))).unsafeRunSync()
val expected =
Map("value" -> Map("value" -> Map("value" -> Map("value" -> Map("value" -> Map().asValue).asValue).asValue).asValue).asValue).asValue
assertEqualsValue(encoded, expected)
}
end RecurrentArgsTest
This results in a stack overflow:
besom.internal.RecurrentArgsTest:
==> X besom.internal.RecurrentArgsTest.encode recurrent type 0.033s java.lang.StackOverflowError: null
at scala.collection.immutable.List.prependedAll(List.scala:148)
at scala.collection.immutable.List$.from(List.scala:684)
at scala.collection.immutable.List$.from(List.scala:681)
at scala.collection.IterableFactory.apply(Factory.scala:103)
at scala.collection.IterableFactory.apply$(Factory.scala:103)
at scala.collection.immutable.List$.apply(List.scala:681)
at besom.internal.RecurrentArgsTest.labels$lzyINIT17$1(EncoderTest.scala:464)
at besom.internal.RecurrentArgsTest.besom$internal$RecurrentArgsTest$Recurrent$$$_$labels$17(EncoderTest.scala:477)
at besom.internal.RecurrentArgsTest$Recurrent$.nameEncoderPairs$lzyINIT17$1(EncoderTest.scala:464)
at besom.internal.RecurrentArgsTest$Recurrent$.nameEncoderPairs$17(EncoderTest.scala:477)
at besom.internal.RecurrentArgsTest$Recurrent$.encoder(EncoderTest.scala:464)
at besom.internal.RecurrentArgsTest$Recurrent$.instances$lzyINIT17$1(EncoderTest.scala:464)
at besom.internal.RecurrentArgsTest$Recurrent$.instances$17(EncoderTest.scala:477)
at besom.internal.RecurrentArgsTest$Recurrent$.nameEncoderPairs$lzyINIT17$1(EncoderTest.scala:464)
at besom.internal.RecurrentArgsTest$Recurrent$.nameEncoderPairs$17(EncoderTest.scala:477)
at besom.internal.RecurrentArgsTest$Recurrent$.encoder(EncoderTest.scala:464)
at besom.internal.RecurrentArgsTest$Recurrent$.instances$lzyINIT17$1(EncoderTest.scala:464)
at besom.internal.RecurrentArgsTest$Recurrent$.instances$17(EncoderTest.scala:477)
at besom.internal.RecurrentArgsTest$Recurrent$.nameEncoderPairs$lzyINIT17$1(EncoderTest.scala:464)
at besom.internal.RecurrentArgsTest$Recurrent$.nameEncoderPairs$17(EncoderTest.scala:477)
at besom.internal.RecurrentArgsTest$Recurrent$.encoder(EncoderTest.scala:464)
at besom.internal.RecurrentArgsTest$Recurrent$.instances$lzyINIT17$1(EncoderTest.scala:464)
at besom.internal.RecurrentArgsTest$Recurrent$.instances$17(EncoderTest.scala:477)
at besom.internal.RecurrentArgsTest$Recurrent$.nameEncoderPairs$lzyINIT17$1(EncoderTest.scala:464)
at besom.internal.RecurrentArgsTest$Recurrent$.nameEncoderPairs$17(EncoderTest.scala:477)
at besom.internal.RecurrentArgsTest$Recurrent$.encoder(EncoderTest.scala:464)
at besom.internal.RecurrentArgsTest$Recurrent$.instances$lzyINIT17$1(EncoderTest.scala:464)
at besom.internal.RecurrentArgsTest$Recurrent$.instances$17(EncoderTest.scala:477)
at besom.internal.RecurrentArgsTest$Recurrent$.nameEncoderPairs$lzyINIT17$1(EncoderTest.scala:464)
...
Two interesting variants:
- adding union causes the test to pass
case class Recurrent(value: Recurrent | Option[Recurrent])
- using
derives
instead ofderived
results in a compile time hang.
lbialy commented
fixed by these changes in codecs.scala
// here: change to by-name parameter
def encoderSum[A](mirror: Mirror.SumOf[A], nameEncoderPairs: => List[(String, Encoder[?])]): Encoder[A] = ...
// here: change to by-name parameter
def encoderProduct[A](nameEncoderPairs: => List[(String, Encoder[?])]): Encoder[A] = ...