Using custom serialization through a mutable structure (eg. a Dict or a custom struct)
When there are circular object references within the datastructure being serialized (tested with Ref & Vector). Both if a struct has a field which references itself, or when 2 objects reference each other
When loading the data, the restored reference (Ref or Vector item) contains the data actually persisted by the custom serialization (in this case a Dict{Symbol, Any}), not the original object (T1 in this case). This can be reproduced both in master and identitypreserv_cs branches.
using JLD2
abstract type AT end
const DSA=Dict{Symbol, Any}
(JLD2.writeas(::Type{T})) where {T <: AT} = DSA
function Base.convert(::Type{DSA}, t::AT)
@info "saving $(typeof(t))"
return DSA(f => getproperty(t, f) for f in fieldnames(typeof(t)))
end
function Base.convert(::Type{T}, dsa::DSA) where {T <: AT}
t= T(; dsa...)
@info "loading $T from $(pointer_from_objref(dsa)) to $(pointer_from_objref(t))"
return t
end
Base.@kwdef mutable struct T1 <: AT
t1::Base.RefValue{Any}
end
function save()
t1 = T1(Ref{Any}(nothing))
t1.t1[] = t1
@info "t1" t1
return save_object("kk.jld2", t1)
end
save()
t1 = load_object("kk.jld2")
@info "t1" t1
┌ Info: t1
└ t1 = T1(Base.RefValue{Any}(Dict{Symbol, Any}(:t1 => Base.RefValue{Any}(#= circular reference @-2 =#))))
The problem occurs when:
Dict
or a customstruct
)When loading the data, the restored reference (Ref or Vector item) contains the data actually persisted by the custom serialization (in this case a
Dict{Symbol, Any}
), not the original object (T1 in this case). This can be reproduced both in master and identitypreserv_cs branches.