JuliaIO / BSON.jl

Other
157 stars 39 forks source link

Cannot recover types of type-parameterized objects #19

Open bicycle1885 opened 5 years ago

bicycle1885 commented 5 years ago

Hi,

I tried to serialize an object with a type parameter and deserialize it from a BSON file. However, it doesn't work because BSON.jl cannot recover the parameter type in a case like below:

using BSON

struct Foo{T}
    data::Vector{T}
end

struct Bar
    data::Vector{Foo{T}} where T
end

obj = Bar([Foo([1])])
buf = IOBuffer()
BSON.bson(buf, Dict(:data => obj.data))
seekstart(buf)
@show typeof(BSON.load(buf)[:data])   # typeof((BSON.load(buf))[:data]) = Array{Any,1}

seekstart(buf)
Bar(BSON.load(buf)[:data])  # This won't work.

I'm using BSON.jl v0.2.1 and Julia 1.0.1 on macOS.

Is this a bug or a limitation of this package? Thank you in advance.

MikeInnes commented 5 years ago

It's more of a shortcut, in the sense that its easy to fall back to storing Vector{Any} in many cases in the BSON format. But it wouldn't be too hard to store the type parameter as well.

Datseris commented 5 years ago

Hi, I want to add that this seems to also occur with standard Julia Vectors as well. A vector of Matrices does not properly store its Matrix type, while a standard Vector{Float64} does.

julia> a = [rand(10, 10) for i in 1:5];
julia> b = rand(1000);
julia> BSON.@save "test.bson" a b

julia> file = BSON.load("test.bson")
Dict{Symbol,Any} with 2 entries:
  :a => Any[[0.930709 0.71512 … 0.350725 0.255823; 0.701098 0.440037 … 0.637…  :b => [0.375467, 0.814742, 0.0895392, 0.0647944, 0.749421, 0.715519, 0.477…
julia> typeof(file[:b])
Array{Float64,1}

julia> typeof(file[:a])
Array{Any,1} # should have been Array{Matrix{Float64}, 1}
Datseris commented 5 years ago

Hm I have to add that this can lead to type-instability that simply erroring code. If someone wants to call a function that has a dispatch signature f(::Vector{<:Matrix}) but also has a dispatch signature for f(::Any) then using the loaded file above will wrongly use the f(::Any) signature, as a Vector{Any} is not a subtype of Vector{Matrix}.

This is more serious than I thought.