disneystreaming / smithy4s

https://disneystreaming.github.io/smithy4s/
Other
348 stars 70 forks source link

Rendering: Traits used recursively in their direct struct members cause a StackOverflowError #1296

Closed kubukoz closed 10 months ago

kubukoz commented 10 months ago

Version: 0.18.3

Minimal example:

$version: "2"

namespace input

@trait
structure Person {
    @Person
    name: String
}
Stack trace

``` java.lang.StackOverflowError at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1694) at software.amazon.smithy.model.Model.toSet(Model.java:773) at software.amazon.smithy.model.Model.getMemberShapes(Model.java:470) at smithy4s.codegen.internals.SmithyToIR.smithy4s$codegen$internals$SmithyToIR$$getAdtParent(SmithyToIR.scala:1124) at smithy4s.codegen.internals.SmithyToIR$UnRef$.$anonfun$unapply$3(SmithyToIR.scala:1148) at scala.Option.orElse(Option.scala:477) at smithy4s.codegen.internals.SmithyToIR$UnRef$.$anonfun$unapply$1(SmithyToIR.scala:1148) at scala.Option.map(Option.scala:242) at smithy4s.codegen.internals.SmithyToIR$UnRef$.unapply(SmithyToIR.scala:1142) at smithy4s.codegen.internals.SmithyToIR.unfoldNodeAndType(SmithyToIR.scala:1183) at smithy4s.codegen.internals.SmithyToIR.$anonfun$unfoldTrait$1(SmithyToIR.scala:1177) at smithy4s.codegen.internals.recursion$.hylo(recursion.scala:41) at smithy4s.codegen.internals.recursion$.ana(recursion.scala:63) at smithy4s.codegen.internals.SmithyToIR.smithy4s$codegen$internals$SmithyToIR$$unfoldTrait(SmithyToIR.scala:1177) at smithy4s.codegen.internals.SmithyToIR.$anonfun$hints$5(SmithyToIR.scala:968) at scala.collection.immutable.List.map(List.scala:246) at smithy4s.codegen.internals.SmithyToIR.smithy4s$codegen$internals$SmithyToIR$$hints(SmithyToIR.scala:968) at smithy4s.codegen.internals.SmithyToIR$ShapeExt.$anonfun$fields$2(SmithyToIR.scala:1001) at scala.collection.StrictOptimizedIterableOps.map(StrictOptimizedIterableOps.scala:100) at scala.collection.StrictOptimizedIterableOps.map$(StrictOptimizedIterableOps.scala:87) at scala.collection.mutable.ArrayBuffer.map(ArrayBuffer.scala:43) at smithy4s.codegen.internals.SmithyToIR$ShapeExt.fields(SmithyToIR.scala:990) at smithy4s.codegen.internals.SmithyToIR.unfoldNodeAndType(SmithyToIR.scala:1186) at smithy4s.codegen.internals.SmithyToIR.$anonfun$unfoldTrait$1(SmithyToIR.scala:1177) at smithy4s.codegen.internals.recursion$.hylo(recursion.scala:41) at smithy4s.codegen.internals.recursion$.ana(recursion.scala:63) at smithy4s.codegen.internals.SmithyToIR.smithy4s$codegen$internals$SmithyToIR$$unfoldTrait(SmithyToIR.scala:1177) at smithy4s.codegen.internals.SmithyToIR.$anonfun$hints$5(SmithyToIR.scala:968) at scala.collection.immutable.List.map(List.scala:246) at smithy4s.codegen.internals.SmithyToIR.smithy4s$codegen$internals$SmithyToIR$$hints(SmithyToIR.scala:968) at smithy4s.codegen.internals.SmithyToIR$ShapeExt.$anonfun$fields$2(SmithyToIR.scala:1001) at scala.collection.StrictOptimizedIterableOps.map(StrictOptimizedIterableOps.scala:100) at scala.collection.StrictOptimizedIterableOps.map$(StrictOptimizedIterableOps.scala:87) at scala.collection.mutable.ArrayBuffer.map(ArrayBuffer.scala:43) at smithy4s.codegen.internals.SmithyToIR$ShapeExt.fields(SmithyToIR.scala:990) at smithy4s.codegen.internals.SmithyToIR.unfoldNodeAndType(SmithyToIR.scala:1186) at smithy4s.codegen.internals.SmithyToIR.$anonfun$unfoldTrait$1(SmithyToIR.scala:1177) at smithy4s.codegen.internals.recursion$.hylo(recursion.scala:41) at smithy4s.codegen.internals.recursion$.ana(recursion.scala:63) at smithy4s.codegen.internals.SmithyToIR.smithy4s$codegen$internals$SmithyToIR$$unfoldTrait(SmithyToIR.scala:1177) at smithy4s.codegen.internals.SmithyToIR.$anonfun$hints$5(SmithyToIR.scala:968) at scala.collection.immutable.List.map(List.scala:246) at smithy4s.codegen.internals.SmithyToIR.smithy4s$codegen$internals$SmithyToIR$$hints(SmithyToIR.scala:968) at smithy4s.codegen.internals.SmithyToIR$ShapeExt.$anonfun$fields$2(SmithyToIR.scala:1001) at scala.collection.StrictOptimizedIterableOps.map(StrictOptimizedIterableOps.scala:100) at scala.collection.StrictOptimizedIterableOps.map$(StrictOptimizedIterableOps.scala:87) ... ```

This is probably not a recent regression.

Note: this works fine:

$version: "2"

namespace input

@trait
structure Person {
    b: B
}

structure B {
    @Person
    s: String
}

Note 2: unions aren't affected:

$version: "2"

namespace input

@trait
union Person {
    @Person(u: "demo")
    name: String
    u: String
}

Note 3: collections (list member, map key/value) are affected.

Note 4: EDIT: collections are a different issue, actually.

ghostbuster91 commented 10 months ago

I am going to take a look at it.