Skip to content

Commit f11c936

Browse files
Merge pull request #115 from JuliaIO/dg/anon
Fix code-gen for `const` fields in `mutable` types
2 parents a34452e + 1a01705 commit f11c936

File tree

4 files changed

+77
-59
lines changed

4 files changed

+77
-59
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "BSON"
22
uuid = "fbb218c0-5317-5bc6-957e-2ee96dd4b1f0"
3-
version = "0.3.5"
3+
version = "0.3.6"
44

55
[compat]
66
julia = "0.7, 1"

src/anonymous.jl

Lines changed: 59 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -93,69 +93,70 @@ end
9393
baremodule __deserialized_types__ end
9494

9595
if VERSION < v"1.7-"
96-
function newstruct_raw(cache, ::Type{TypeName}, d, init)
97-
name = raise_recursive(d[:data][2], cache, init)
98-
name = isdefined(__deserialized_types__, name) ? gensym() : name
99-
tn = ccall(:jl_new_typename_in, Ref{Core.TypeName}, (Any, Any),
100-
name, __deserialized_types__)
101-
cache[d] = tn
102-
names, super, parameters, types, has_instance,
103-
abstr, mutabl, ninitialized = map(x -> raise_recursive(x, cache, init), d[:data][3:end-1])
104-
tn.names = names
105-
ndt = ccall(:jl_new_datatype, Any, (Any, Any, Any, Any, Any, Any, Cint, Cint, Cint),
106-
tn, tn.module, super, parameters, names, types,
107-
abstr, mutabl, ninitialized)
108-
ty = tn.wrapper = ndt.name.wrapper
109-
ccall(:jl_set_const, Cvoid, (Any, Any, Any), tn.module, tn.name, ty)
110-
if has_instance && !isdefined(ty, :instance)
111-
# use setfield! directly to avoid `fieldtype` lowering expecting to see a Singleton object already on ty
112-
Core.setfield!(ty, :instance, ccall(:jl_new_struct, Any, (Any, Any...), ty))
113-
end
114-
mt = raise_recursive(d[:data][end], cache, init)
115-
if mt != nothing
116-
mtname, defs, maxa, kwsorter = mt
117-
tn.mt = ccall(:jl_new_method_table, Any, (Any, Any), name, tn.module)
118-
tn.mt.name = mtname
119-
tn.mt.max_args = maxa
120-
for def in defs
121-
isdefined(def, :sig) || continue
122-
ccall(:jl_method_table_insert, Cvoid, (Any, Any, Ptr{Cvoid}), tn.mt, def, C_NULL)
96+
function newstruct_raw(cache, ::Type{TypeName}, d, init)
97+
name = raise_recursive(d[:data][2], cache, init)
98+
name = isdefined(__deserialized_types__, name) ? gensym() : name
99+
tn = ccall(:jl_new_typename_in, Ref{Core.TypeName}, (Any, Any),
100+
name, __deserialized_types__)
101+
cache[d] = tn
102+
names, super, parameters, types, has_instance,
103+
abstr, mutabl, ninitialized = map(x -> raise_recursive(x, cache, init), d[:data][3:end-1])
104+
tn.names = names
105+
ndt = ccall(:jl_new_datatype, Any, (Any, Any, Any, Any, Any, Any, Cint, Cint, Cint),
106+
tn, tn.module, super, parameters, names, types,
107+
abstr, mutabl, ninitialized)
108+
ty = tn.wrapper = ndt.name.wrapper
109+
ccall(:jl_set_const, Cvoid, (Any, Any, Any), tn.module, tn.name, ty)
110+
if has_instance && !isdefined(ty, :instance)
111+
# use setfield! directly to avoid `fieldtype` lowering expecting to see a Singleton object already on ty
112+
Core.setfield!(ty, :instance, ccall(:jl_new_struct, Any, (Any, Any...), ty))
113+
end
114+
mt = raise_recursive(d[:data][end], cache, init)
115+
if mt != nothing
116+
mtname, defs, maxa, kwsorter = mt
117+
tn.mt = ccall(:jl_new_method_table, Any, (Any, Any), name, tn.module)
118+
tn.mt.name = mtname
119+
tn.mt.max_args = maxa
120+
for def in defs
121+
isdefined(def, :sig) || continue
122+
ccall(:jl_method_table_insert, Cvoid, (Any, Any, Ptr{Cvoid}), tn.mt, def, C_NULL)
123+
end
123124
end
125+
return tn
124126
end
125-
return tn
126-
end
127127
else
128-
function newstruct_raw(cache, ::Type{TypeName}, d, init)
129-
name = raise_recursive(d[:data][2], cache, init)
130-
name = isdefined(__deserialized_types__, name) ? gensym() : name
131-
tn = ccall(:jl_new_typename_in, Ref{Core.TypeName}, (Any, Any),
132-
name, __deserialized_types__)
133-
cache[d] = tn
134-
names, super, parameters, types, has_instance, atomicfields,
135-
abstr, mutabl, ninitialized = map(x -> raise_recursive(x, cache, init), d[:data][3:end-1])
136-
tn.names = names
137-
ndt = ccall(:jl_new_datatype, Any, (Any, Any, Any, Any, Any, Any, Any, Cint, Cint, Cint),
138-
tn, tn.module, super, parameters, names, types, atomicfields,
139-
abstr, mutabl, ninitialized)
140-
ty = tn.wrapper = ndt.name.wrapper
141-
ccall(:jl_set_const, Cvoid, (Any, Any, Any), tn.module, tn.name, ty)
142-
if has_instance && !isdefined(ty, :instance)
143-
# use setfield! directly to avoid `fieldtype` lowering expecting to see a Singleton object already on ty
144-
Core.setfield!(ty, :instance, ccall(:jl_new_struct, Any, (Any, Any...), ty))
145-
end
146-
mt = raise_recursive(d[:data][end], cache, init)
147-
if mt != nothing
148-
mtname, defs, maxa, kwsorter = mt
149-
tn.mt = ccall(:jl_new_method_table, Any, (Any, Any), name, tn.module)
150-
tn.mt.name = mtname
151-
tn.mt.max_args = maxa
152-
for def in defs
153-
isdefined(def, :sig) || continue
154-
ccall(:jl_method_table_insert, Cvoid, (Any, Any, Ptr{Cvoid}), tn.mt, def, C_NULL)
128+
function newstruct_raw(cache, ::Type{TypeName}, d, init)
129+
name = raise_recursive(d[:data][2], cache, init)
130+
name = isdefined(__deserialized_types__, name) ? gensym() : name
131+
tn = ccall(:jl_new_typename_in, Ref{Core.TypeName}, (Any, Any),
132+
name, __deserialized_types__)
133+
cache[d] = tn
134+
names, super, parameters, types, has_instance, atomicfields,
135+
abstr, mutabl, ninitialized = map(x -> raise_recursive(x, cache, init), d[:data][3:end-1])
136+
ndt = ccall(:jl_new_datatype, Any, (Any, Any, Any, Any, Any, Any, Any, Cint, Cint, Cint),
137+
tn, tn.module, super, parameters, names, types, atomicfields,
138+
abstr, mutabl, ninitialized)
139+
# ty = tn.wrapper = ndt.name.wrapper
140+
ty = ndt.name.wrapper
141+
ccall(:jl_set_const, Cvoid, (Any, Any, Any), tn.module, tn.name, ty)
142+
if has_instance && !isdefined(ty, :instance)
143+
# use setfield! directly to avoid `fieldtype` lowering expecting to see a Singleton object already on ty
144+
Core.setfield!(ty, :instance, ccall(:jl_new_struct, Any, (Any, Any...), ty))
145+
end
146+
mt = raise_recursive(d[:data][end], cache, init)
147+
if mt != nothing
148+
mtname, defs, maxa, kwsorter = mt
149+
mt = ccall(:jl_new_method_table, Any, (Any, Any), name, tn.module)
150+
mt.name = mtname
151+
mt.max_args = maxa
152+
ccall(:jl_set_nth_field, Cvoid, (Any, Csize_t, Any), tn, Base.fieldindex(Core.TypeName, :mt)-1, mt)
153+
for def in defs
154+
isdefined(def, :sig) || continue
155+
ccall(:jl_method_table_insert, Cvoid, (Any, Any, Ptr{Cvoid}), mt, def, C_NULL)
156+
end
155157
end
158+
return tn
156159
end
157-
return tn
158-
end
159160
end
160161

161162
# Function Types

test/const_fields.jl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
@testset "Immutable Fields" begin
2+
mutable struct ConstFields
3+
a::Int
4+
const b::Vector{Float64}
5+
end
6+
7+
a = ConstFields(1, [1.])
8+
b = BSON.roundtrip(a)
9+
@test typeof(a) == typeof(b)
10+
map(fieldnames(ConstFields)) do f
11+
@test getproperty(a, f) == getproperty(b, f)
12+
end
13+
end

test/runtests.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ end
4242

4343
@testset "BSON" begin
4444

45+
if VERSION >= v"1.8"
46+
include("const_fields.jl")
47+
end
48+
4549
@testset "Primitive Types" begin
4650
@test roundtrip_equal(nothing)
4751
@test roundtrip_equal(1)

0 commit comments

Comments
 (0)