TOML: using to_toml option may produce incorrect TOML

This is a simplified example to illustrate the issue I’m seeing with using the TOML writer with the to_toml option for writing a custom type. It seems that when using the to_toml option, TOML print doesn’t print the correct TOML.

I expect the hello = "hello" to not be combined with the [b] table.

I’m using Julia 1.8 Silicon on an M1 Mac.

Just looking to see if anyone else is seeing this and if my understanding is correct.

using TOML

struct Foo
    a::Int64
    b::Float64
end

struct Bar
    c::Float64
    d::String
end


f = Foo(2,9.9)
b = Bar(1.345, "hello")

dd = Dict("hello"=>"world", "f"=>f,  "b"=>b)

toDict(foo::Foo) = Dict("a"=>foo.a, "b"=>foo.b)
toDict(bar::Bar) = Dict("c"=>bar.c, "d"=>bar.d)

TOML.print(toDict,dd)

which results in the “hello” being added to the b table in the TOML.

[f]
b = 9.9
a = 2

[b]
c = 1.345
d = "hello"
hello = "world"

This does seem to be a bug in TOML.jl. It happens when there’s a simple (non-Dict) entry like "hello" => "world" along with custom entries like f and b here that become Dicts only after the conversion function.

(Internally, it tries to print all the simple non-Dict entries first, but when something turns out to be not a simple value after conversion, it immediately prints it with a recursive call

        if is_tabular(value)
            _print(f, io, Dict(key => value); indent, first_block, sorted, by)

rather than defer it for later after all the non-Dict entries have been printed.)