Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix anonymous method serialization for Julia v1.10 #125

Merged
merged 3 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions src/anonymous.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ function newstruct!(meth::Method, mod, name, file, line, sig,
meth.pure = ast.pure
return meth
end
else
elseif VERSION < v"1.10-"
function newstruct!(meth::Method, mod, name, file, line, sig,
syms, nargs, isva, nospecialize, ast)
meth.module = mod
Expand All @@ -58,6 +58,22 @@ function newstruct!(meth::Method, mod, name, file, line, sig,
meth.pure = ast.pure
return meth
end
else
function newstruct!(meth::Method, mod, name, file, line, sig,
syms, nargs, isva, nospecialize, ast)
meth.module = mod
meth.name = name
meth.file = file
meth.line = line
meth.sig = sig
setfield!(meth, syms_fieldname, syms)
meth.nospecialize = nospecialize
meth.nargs = nargs
meth.isva = isva
meth.source = ast
meth.purity = ast.purity
return meth
end
end

# Type Names
Expand Down Expand Up @@ -92,7 +108,7 @@ end

baremodule __deserialized_types__ end

if VERSION < v"1.7-"
@static if VERSION < v"1.7-"
function newstruct_raw(cache, ::Type{TypeName}, d, init)
name = raise_recursive(d[:data][2], cache, init)
name = isdefined(__deserialized_types__, name) ? gensym() : name
Expand Down Expand Up @@ -148,7 +164,7 @@ else
mtname, defs, maxa, kwsorter = mt
mt = ccall(:jl_new_method_table, Any, (Any, Any), name, tn.module)
mt.name = mtname
mt.max_args = maxa
@atomic mt.max_args = maxa
ccall(:jl_set_nth_field, Cvoid, (Any, Csize_t, Any), tn, Base.fieldindex(Core.TypeName, :mt)-1, mt)
for def in defs
isdefined(def, :sig) || continue
Expand Down
15 changes: 13 additions & 2 deletions src/extensions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,16 @@

# Structs

structdata(x) = isprimitivetype(typeof(x)) ? reinterpret_(UInt8, [x]) :
Any[getfield(x,f) for f in fieldnames(typeof(x)) if isdefined(x, f)]
struct Undef end
function structdata(x)
if isprimitivetype(typeof(x))
return reinterpret_(UInt8, [x])
elseif !ismutabletype(typeof(x))
return Any[getfield(x,f) for f in fieldnames(typeof(x)) if isdefined(x, f)]
else # mutable structs can have defined fields following undefined fields
return Any[isdefined(x, f) ? getfield(x,f) : Undef() for f in fieldnames(typeof(x))]
end
end

function lower(x)
BSONDict(:tag => "struct", :type => typeof(x), :data => structdata(x))
Expand All @@ -119,6 +127,7 @@

function newstruct!(x, fs...)
for (i, f) = enumerate(fs)
isa(f, Undef) && continue
f = convert(fieldtype(typeof(x),i), f)
ccall(:jl_set_nth_field, Nothing, (Any, Csize_t, Any), x, i-1, f)
end
Expand All @@ -136,6 +145,7 @@
x = initstruct(T)

for (i, f) = enumerate(xs)
isa(f, Undef) && continue

Check warning on line 148 in src/extensions.jl

View check run for this annotation

Codecov / codecov/patch

src/extensions.jl#L148

Added line #L148 was not covered by tests
f = convert(fieldtype(typeof(x),i), f)
ccall(:jl_set_nth_field, Nothing, (Any, Csize_t, Any), x, i-1, f)
end
Expand All @@ -154,6 +164,7 @@
x = initstruct(T)

for (i, f) = enumerate(xs)
isa(f, Undef) && continue

Check warning on line 167 in src/extensions.jl

View check run for this annotation

Codecov / codecov/patch

src/extensions.jl#L167

Added line #L167 was not covered by tests
f = convert(fieldtype(typeof(x),i), f)
ccall(:jl_set_nth_field, Nothing, (Any, Csize_t, Any), x, i-1, f)
end
Expand Down
23 changes: 23 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,25 @@ struct Bar
Bar() = new()
end

mutable struct Baz
x
y
z
Baz() = new()
end

function is_field_equal(a, b, field::Symbol)
!isdefined(a, field) && return !isdefined(b, field)
!isdefined(b, field) && return false
return getfield(a, field) == getfield(b, field)
end

function Base.:(==)(a::Baz, b::Baz)
return is_field_equal(a, b, :x) &&
is_field_equal(a, b, :y) &&
is_field_equal(a, b, :z)
end

module A
using DataFrames, BSON
d = DataFrame(a = 1:10, b = rand(10))
Expand Down Expand Up @@ -72,6 +91,10 @@ end
@test_broken roundtrip_equal(Dict(:x => x))

@test roundtrip_equal(Bar())

o = Baz()
o.y = 1
@test roundtrip_equal(o)
end

@testset "Complex Types" begin
Expand Down
Loading