diff --git a/CHANGELOG.md b/CHANGELOG.md index ff172ae9..a9cf5270 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.5.2 + - Remove left-over warning + - Restrict warning for storing `Function` objects to `anonymous` functions. + ## 0.5.1 - Bugfix and added test for bug introduced in v0.5.0 diff --git a/Project.toml b/Project.toml index 571a98d9..838735c1 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "JLD2" uuid = "033835bb-8acc-5ee8-8aae-3f567f8a3819" -version = "0.5.1" +version = "0.5.2" [deps] FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" diff --git a/src/data/reconstructing_datatypes.jl b/src/data/reconstructing_datatypes.jl index 1f2c58ed..01e6fee4 100644 --- a/src/data/reconstructing_datatypes.jl +++ b/src/data/reconstructing_datatypes.jl @@ -592,9 +592,8 @@ function reconstruct_odr(f::JLDFile, dt::CompoundDatatype, i = findfirst(==(Symbol(k)), dt.names) if typeref != NULL_REFERENCE dtrr = jltype(f, f.datatype_locations[typeref]) - odr_sizeof(dtrr) != 0 && @warn "Field $k has non-zero size in file, this should not happen" elseif !isnothing(i) - offset = dt.offsets[i] + offset == dt.offsets[i] || throw(InternalError("Field offsets were incorrectly mapped.")) dtrr = jltype(f, dt.members[i]) else throw(InternalError("Field $k not found in datatype")) diff --git a/src/data/writing_datatypes.jl b/src/data/writing_datatypes.jl index 68570202..cc414c17 100644 --- a/src/data/writing_datatypes.jl +++ b/src/data/writing_datatypes.jl @@ -219,7 +219,6 @@ end if f.disable_commit throw(ArgumentError("Attempted to commit DataType $readas but committing is disabled.")) end - io = f.io # This needs to be written this way or type inference gets unhappy... # Also needs to happen here so that we write the DataType type @@ -229,7 +228,7 @@ end offset = f.end_of_data - seek(io, offset) + seek(f.io, offset) id = length(f.datatypes)+1 h5o = h5offset(f, offset) cdt = CommittedDatatype(h5o, id) @@ -383,15 +382,15 @@ const H5TYPE_DATATYPE = CompoundDatatype( ) function h5fieldtype(f::JLDFile, ::Type{T}, readas::Type, ::Initialized) where T<:DataType + if f.disable_commit + throw(ArgumentError("Attempted to commit DataType $readas but committing is disabled.")) + end if !(readas <: DataType) || (T isa Type{Type{T}} where T) @lookup_committed f readas return commit(f, H5TYPE_DATATYPE, DataType, readas) end @lookup_committed f DataType - if f.disable_commit - throw(ArgumentError("Attempted to commit DataType $readas but committing is disabled.")) - end io = f.io offset = f.end_of_data @@ -446,6 +445,11 @@ end function h5convert!(out::Pointers, ::DataTypeODR, f::JLDFile, T::DataType, wsession::JLDWriteSession) t = typename(T) + if T <: Function && isgensym(nameof(T.instance)) + @warn LazyString("Attempting to store ", T, ".\n", + "JLD2 only stores functions by name.\n", + " This may not be useful for anonymous functions.") + end store_vlen!(out, UInt8, f, unsafe_wrap(Vector{UInt8}, t), f.datatype_wsession) if isempty(T.parameters) h5convert_uninitialized!(out+odr_sizeof(Vlen{UInt8}), Vlen{UInt8}) @@ -627,9 +631,6 @@ end # fieldodr, but actually encoding the data for things that odr stores # as references @nospecializeinfer function odr(@nospecialize(T::Type)) - if T <: Function - @warn LazyString("Attempting to store ", T, ".\n Function types cannot be propertly stored in JLD2 files.\n Loading may yield unexpected results.") - end if !hasdata(T) # A pointer singleton or ghost. We need to write something, but we'll # just write a single byte. diff --git a/src/julia_compat.jl b/src/julia_compat.jl index f17e348e..a577bebb 100644 --- a/src/julia_compat.jl +++ b/src/julia_compat.jl @@ -28,4 +28,10 @@ end end else using Base: @nospecializeinfer +end + +@static if VERSION < v"1.7.0" + isgensym(s::Symbol) = '#' in string(s) +else + using Base: isgensym end \ No newline at end of file diff --git a/test/loadsave.jl b/test/loadsave.jl index ec87d90b..e4e0a434 100644 --- a/test/loadsave.jl +++ b/test/loadsave.jl @@ -745,44 +745,47 @@ end end @testset "Disable committing datatypes" begin - cd(mktempdir()) do - jldopen("test.jld2", "w") do f - f.disable_commit = true + fn = joinpath(mktempdir(), "disable_committing_datatypes.jld2") + jldopen(fn, "w") do f + f.disable_commit = true - @test_throws ArgumentError f["1"] = Dict(1=>2) - @test_throws ArgumentError f["2"] = Vector{Float64} - @test_throws ArgumentError f["3"] = (1,2,3) - # this could eventually be allowed - @test_throws ArgumentError f["4"] = (; a=1, b=2) - end + @test_throws ArgumentError f["1"] = Dict(1=>2) + @test_throws ArgumentError f["2"] = Vector{Float64} + @test_throws ArgumentError f["3"] = (1,2,3) + @test_throws ArgumentError f["4"] = :asymbol + # No throw + f["5"] = "a string" + # this could eventually be allowed + @test_throws ArgumentError f["4"] = (; a=1, b=2) end end @testset "Missing Types in Tuples" begin - cd(mktempdir()) do - eval(:(module ModuleWithFunction - fun(x) = x+1 - end)) - if VERSION ≥ v"1.7" - @test_warn( - contains("Function types cannot"), - eval(:(save_object("test.jld2", (1, ModuleWithFunction.fun, 2)))) - ) - else - eval(:(save_object("test.jld2", (1, ModuleWithFunction.fun, 2)))) - end - obj = load_object("test.jld2") - @test length(obj) == 3 - @test obj[1] == 1 - @test obj[2] == eval(:(ModuleWithFunction.fun)) - @test obj[3] == 2 - - eval(:(module ModuleWithFunction end)) - obj = load_object("test.jld2") - @test length(obj) == 3 - @test obj[1] == 1 - @test JLD2.isreconstructed(obj[2]) - @test obj[3] == 2 + fn = joinpath(mktempdir(), "missing_types_in_tuple.jld2") + eval(:(module ModuleWithFunction + fun(x) = x+1 + end)) + eval(:(save_object($fn, (1, ModuleWithFunction.fun, 2)))) + obj = load_object(fn) + @test length(obj) == 3 + @test obj[1] == 1 + @test obj[2] == eval(:(ModuleWithFunction.fun)) + @test obj[3] == 2 + + eval(:(module ModuleWithFunction end)) + obj = load_object(fn) + @test length(obj) == 3 + @test obj[1] == 1 + @test JLD2.isreconstructed(obj[2]) + @test obj[3] == 2 + +end + +if VERSION ≥ v"1.7" + @testset "Storing an anonymous function" begin + fn = joinpath(mktempdir(), "storing_anon_function.jld2") + f = x -> x+1 + @test_warn contains("Attempting to store") save_object(fn, f) end end \ No newline at end of file