Thanks a lot, @tecosaur! About.jl became one of the most important packages in my Julia workflow. I can only recommend to every REPL user to put it in startup.jl and append a |> about whenever you want to know something about basically anything there is in Julia.
I am especially thankful for the patience with which you fix bugs whenever I come up with another special case. ![]()
I am still struggling a bit to fully understand the memory layout for the non-isbitstype case.
x has 4 bytes, followed by 4 bytes of padding followed by 8 bytes to the “pointer” to either the UnionAll type Vector or Nothing, where the type information is (somehow) taken from the memory address where the pointer points to.
I haven’t fully understand the Julia source code, but if I got this right, the field access will not use a separate union type tag if jl_field_isptr is true. Otherwise it will go into the jl_is_uniontype branch.
I think isptr is true:
const FieldDesc8 = Tuple{UInt8, UInt8}
MyStruct32{Vector}.layout + sizeof(Base.DataTypeLayout) + sizeof(FieldDesc8) |> Ptr{FieldDesc8} |> unsafe_load |> first |> (x -> x & 0b1) |> Bool
See the definitions of jl_fielddesc8_t and jl_datatype_layout_t.
But if this is correct, doesn’t it mean that Base.summarysize is incorrect, as it returns:
julia> Union{Nothing, Vector} |> Base.SummarySize(IdDict(), Any[], Int[], Union{}, Union{})
16
See the definition of Base.summarysize.
Can anyone with more insights please point out my error or confirm that we should fix Base.summarysize?