JSON3 stack overflow with generics

When running the following code, I get a StackOverflow error.
I do not understand why that error happens. It seems to have something to do with the compilers reasoning about generics.
Any input on why that error happens and what it means would be greatly appreciated.

using JSON3
using StructTypes

struct A{T}
    name::String
end

struct B{T}
    default::Ref{Union{T,Nothing}}
end

StructTypes.StructType(::Type{A{T}}) where T = StructTypes.Struct()

StructTypes.StructType(::Type{B{T}}) where T = StructTypes.Struct()

function f(settings::Vector{A})
    for setting_template in settings
        g(setting_template)
    end
end

function g(setting_template::A{T}) where T
    json_string = ""
    JSON3.read(json_string, B{T})
end

a1 = A{Int}("a")
a2 = A{Bool}("b")

f([a1,a2])

When executing this code I get the following output:
(after that an error is thrown because we try to JSON3.read an empty string, please disregard)

Internal error: encountered unexpected error in runtime:
StackOverflowError()
subtype_ccheck at /cygdrive/c/buildbot/worker/package_win64/build/src\subtype.c:546
var_lt at /cygdrive/c/buildbot/worker/package_win64/build/src\subtype.c:618
subtype at /cygdrive/c/buildbot/worker/package_win64/build/src\subtype.c:1231
var_lt at /cygdrive/c/buildbot/worker/package_win64/build/src\subtype.c:612
subtype at /cygdrive/c/buildbot/worker/package_win64/build/src\subtype.c:1231
exists_subtype at /cygdrive/c/buildbot/worker/package_win64/build/src\subtype.c:1395 [inlined]
forall_exists_subtype at /cygdrive/c/buildbot/worker/package_win64/build/src\subtype.c:1423
subtype_ccheck at /cygdrive/c/buildbot/worker/package_win64/build/src\subtype.c:555
var_lt at /cygdrive/c/buildbot/worker/package_win64/build/src\subtype.c:618
subtype at /cygdrive/c/buildbot/worker/package_win64/build/src\subtype.c:1231
var_lt at /cygdrive/c/buildbot/worker/package_win64/build/src\subtype.c:612
subtype at /cygdrive/c/buildbot/worker/package_win64/build/src\subtype.c:1231
exists_subtype at /cygdrive/c/buildbot/worker/package_win64/build/src\subtype.c:1395 [inlined]
…
unknown function (ip: 000000005f039e23)
with_logstate at .\logging.jl:511
with_logger at .\logging.jl:623 [inlined]
#63 at c:\Users\lklein.vscode\extensions\julialang.language-julia-1.7.12\scripts\packages\VSCodeServer\src\eval.jl:225
unknown function (ip: 000000005f0381e3)
jl_apply at /cygdrive/c/buildbot/worker/package_win64/build/src\julia.h:1788 [inlined]
jl_f__call_latest at /cygdrive/c/buildbot/worker/package_win64/build/src\builtins.c:757
#invokelatest#2 at .\essentials.jl:716 [inlined]
invokelatest at .\essentials.jl:714
jl_apply at /cygdrive/c/buildbot/worker/package_win64/build/src\julia.h:1788 [inlined]
do_apply at /cygdrive/c/buildbot/worker/package_win64/build/src\builtins.c:713
macro expansion at c:\Users\lklein.vscode\extensions\julialang.language-julia-1.7.12\scripts\packages\VSCodeServer\src\eval.jl:34 [inlined]
#61 at .\task.jl:429
unknown function (ip: 000000005f015ec3)
jl_apply at /cygdrive/c/buildbot/worker/package_win64/build/src\julia.h:1788 [inlined]
start_task at /cygdrive/c/buildbot/worker/package_win64/build/src\task.c:877

Can you try this instead:

struct B{T}
    default::Union{T,Nothing}
end

Thanks for your reply!
When running with your suggested change, the error no longer happens.
Unfortunately that does not fix my problem, as I have a lot of side constrains and just posted a MWE to reproduce the bug.
Any idea on why exactly that change causes the bug to happen/not happen?

The stack overflow seems to happen during type inference itself. The code here doesn’t have anything obvious that would lead to that, so the issue must be with the StructType declarations.

StructTypes.Struct says it should be used when a type’s “fields should be used directly when serializing/deserializing”. B’s field is a Ref which I don’t think should be directly serialized/deserialized. @jd-foster’s suggestion changes B to have a type that can be directly serialized, so makes it appropriate for StructTypes.Struct. But if that’s infeasible due to other constraints, you may have to change its StructType to Mutable or Custom. Opening an issue and asking the StructTypes devs would probably help with deciding which course to take exactly.

1 Like

FTR the stack overflow doesn’t reproduce on either the latest Julia release or on nightly Julia, at least on my Linux system (system stack size setting might matter).
This doesn’t fix the issue, though.