From a4f298056ed8147711601f2070014467288f9452 Mon Sep 17 00:00:00 2001 From: JonasIsensee Date: Sat, 10 Sep 2022 09:28:48 +0200 Subject: [PATCH] const fields in mutable structs (#414) * testing const fields in mutable structs * support const fields in mutable structs * bump version Co-authored-by: Jonas Isensee --- CHANGELOG.md | 3 +++ Project.toml | 2 +- src/data/reconstructing_datatypes.jl | 9 +++++++-- test/loadsave.jl | 27 +++++++++++++++++++++++++++ 4 files changed, 38 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 85791692..9fcaaa4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 0.4.23 + - Support for `const` fields in mutable structs + ## 0.4.22 - Fix reconstruction of partially intialized structs diff --git a/Project.toml b/Project.toml index e923e72d..0f1f7e15 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "JLD2" uuid = "033835bb-8acc-5ee8-8aae-3f567f8a3819" -version = "0.4.22" +version = "0.4.23" [deps] FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" diff --git a/src/data/reconstructing_datatypes.jl b/src/data/reconstructing_datatypes.jl index 6449f023..9165547e 100644 --- a/src/data/reconstructing_datatypes.jl +++ b/src/data/reconstructing_datatypes.jl @@ -540,9 +540,14 @@ jlconvert(::ReadRepresentation{Core.TypeofBottom,nothing}, f::JLDFile, ptr::Ptr, if odr === nothing # Type is not stored or single instance newi = Expr(:new, ttype) - push!(args, :(setfield!(obj, $fni, $newi))) + # use jl_set_nth_field instead of setfield! since the former also works for const fields + # in mutable structs. + push!(args, :(ccall(:jl_set_nth_field, Nothing, (Any, Csize_t, Any), obj, ($i)-1, $newi))) else - loadfield = :(setfield!(obj, $fni, rconvert($ttype, jlconvert($rr, f, ptr+$offset, NULL_REFERENCE)::$rtype)::$ttype)) + loadfield = quote + fieldval = rconvert($ttype, jlconvert($rr, f, ptr+$offset, NULL_REFERENCE)::$rtype)::$ttype + ccall(:jl_set_nth_field, Nothing, (Any, Csize_t, Any), obj, ($i)-1, fieldval) + end if jlconvert_canbeuninitialized(rr) push!(args, :(jlconvert_isinitialized($rr, ptr+$offset) && $(loadfield))) else diff --git a/test/loadsave.jl b/test/loadsave.jl index 681f5e7b..d7e3a430 100644 --- a/test/loadsave.jl +++ b/test/loadsave.jl @@ -513,4 +513,31 @@ end @test_throws UndefRefError fu.x end +end + +if VERSION ≥ v"1.8" + + struct SingletonStruct end + + # This is a workaround since for old julia versions this syntax is not allowed and the parser + # is eager and attempts to parse this piece of code anyway + eval(Meta.parse("""mutable struct WrappedSingleton + x::Int + const y::Vector{Int} + const z::SingletonStruct + end + """)) + + @testset "Constant fields in mutable structs (>v1.8) - Issue #410" begin + mktempdir() do folder + # The real test here is that it doesn't fail in v1.8 + b = WrappedSingleton(1, [2,3], SingletonStruct()) + save("test.jld2", "b", b) + bloaded = load("test.jld2", "b") + @test b.x == bloaded.x + @test b.y == bloaded.y + @test b.z == bloaded.z + end + end + end \ No newline at end of file