Skip to content

Commit 379fb3c

Browse files
Merge pull request #102 from darsnack/darsnack/mutable-fix
Fix errors on 1.7
2 parents 9a6a6b2 + e4a5d3d commit 379fb3c

File tree

6 files changed

+108
-17
lines changed

6 files changed

+108
-17
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# BSON
22

3-
[![Build Status](https://travis-ci.org/JuliaIO/BSON.jl.svg?branch=master)](https://travis-ci.org/JuliaIO/BSON.jl)
3+
[![CI](https://github.com/JuliaIO/BSON.jl/actions/workflows/ci.yml/badge.svg)](https://github.com/JuliaIO/BSON.jl/actions/workflows/ci.yml)
44

55
BSON.jl is a Julia package for working with the [Binary JSON](http://bsonspec.org/) serialisation format. It can be used as a general store for Julia data structures, with the following features:
66

src/BSON.jl

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ module BSON
33
using Core: SimpleVector, TypeName
44
export bson
55

6-
using Core: SimpleVector, TypeName
7-
86
const BSONDict = Dict{Symbol,Any}
97
const BSONArray = Vector{Any}
108
const Primitive = Union{Nothing,Bool,Int32,Int64,Float64,String,Vector{UInt8},BSONDict,BSONArray}

src/anonymous.jl

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ function newstruct!(meth::Method, mod, name, file, line, sig,
6060
end
6161
end
6262

63+
# Type Names
64+
65+
if VERSION < v"1.7-"
6366
function structdata(t::TypeName)
6467
primary = Base.unwrap_unionall(t.wrapper)
6568
mt = !isdefined(t, :mt) ? nothing :
@@ -69,11 +72,27 @@ function structdata(t::TypeName)
6972
primary.types, isdefined(primary, :instance), isabstracttype(primary),
7073
ismutabletype(primary), primary.ninitialized, mt]
7174
end
75+
else
76+
# see https://github.com/JuliaLang/julia/pull/41018 for changes
77+
function structdata(t::TypeName)
78+
primary = Base.unwrap_unionall(t.wrapper)
79+
mt = !isdefined(t, :mt) ? nothing :
80+
[t.mt.name, collect(Base.MethodList(t.mt)), t.mt.max_args,
81+
isdefined(t.mt, :kwsorter) ? t.mt.kwsorter : nothing]
82+
[Base.string(VERSION), t.name, t.names, primary.super, primary.parameters,
83+
primary.types, isdefined(primary, :instance), t.atomicfields, isabstracttype(primary),
84+
ismutable(primary), Core.Compiler.datatype_min_ninitialized(primary), mt]
85+
end
86+
end
7287

73-
# Type Names
88+
if VERSION >= v"1.7-"
89+
structdata(x::Core.TypeofVararg) =
90+
Any[getfield(x, f) for f in fieldnames(typeof(x)) if isdefined(x, f)]
91+
end
7492

7593
baremodule __deserialized_types__ end
7694

95+
if VERSION < v"1.7-"
7796
function newstruct_raw(cache, ::Type{TypeName}, d, init)
7897
name = raise_recursive(d[:data][2], cache, init)
7998
name = isdefined(__deserialized_types__, name) ? gensym() : name
@@ -105,6 +124,39 @@ function newstruct_raw(cache, ::Type{TypeName}, d, init)
105124
end
106125
return tn
107126
end
127+
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)
155+
end
156+
end
157+
return tn
158+
end
159+
end
108160

109161
# Function Types
110162

src/extensions.jl

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ function newstruct!(x, fs...)
110110
return x
111111
end
112112

113+
if VERSION < v"1.7-"
113114
function newstruct(T, xs...)
114115
if !ismutabletype(T)
115116
flds = Any[convert(fieldtype(T, i), x) for (i,x) in enumerate(xs)]
@@ -127,6 +128,25 @@ function newstruct(T, xs...)
127128

128129
end
129130
end
131+
else
132+
function newstruct(T, xs...)
133+
if !ismutabletype(T)
134+
flds = Any[convert(fieldtype(T, i), x) for (i,x) in enumerate(xs)]
135+
return ccall(:jl_new_structv, Any, (Any,Ptr{Cvoid},UInt32), T, flds, length(flds))
136+
else
137+
# Manual inline of newstruct! to work around bug
138+
# https://github.com/MikeInnes/BSON.jl/issues/2#issuecomment-452204339
139+
x = initstruct(T)
140+
141+
for (i, f) = enumerate(xs)
142+
f = convert(fieldtype(typeof(x),i), f)
143+
ccall(:jl_set_nth_field, Nothing, (Any, Csize_t, Any), x, i-1, f)
144+
end
145+
x
146+
147+
end
148+
end
149+
end
130150

131151
function newstruct_raw(cache, T, d, init)
132152
x = cache[d] = initstruct(T)

src/write.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,11 @@ lower(x::Primitive) = x
4343

4444
import Base: RefValue
4545

46+
if VERSION < v"1.7-"
47+
ismutable(T) = !isa(T, DataType) || T.mutable
48+
else
4649
ismutable(T) = !isa(T, DataType) || ismutabletype(T)
50+
end
4751
ismutable(::Type{String}) = false
4852

4953
typeof_(x) = typeof(x)

test/runtests.jl

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ module A
3434
bson("test_25_dataframe.bson", Dict(:d=>d))
3535
end
3636

37+
struct NoInit
38+
x::Int
39+
40+
NoInit() = new()
41+
end
42+
3743
@testset "BSON" begin
3844

3945
@testset "Primitive Types" begin
@@ -101,21 +107,32 @@ end
101107
@test x.x === x
102108
end
103109

110+
@testset "Undefined References" begin
111+
# from Issue #3
112+
d = Dict(:a => 1, :b => Dict(:c => 3, :d => Dict("e" => 5)))
113+
@test roundtrip_equal(d)
114+
115+
# from Issue #43
116+
x = Array{String, 1}(undef, 5)
117+
x[1] = "a"
118+
x[4] = "d"
119+
@test_broken roundtrip_equal(Dict(:x => x))
120+
121+
x = NoInit()
122+
@test roundtrip_equal(x)
123+
end
124+
104125
@testset "Anonymous Functions" begin
105126
f = x -> x+1
106-
if VERSION < v"1.7-"
107-
f2 = BSON.roundtrip(f)
108-
@test f2(5) == f(5)
109-
@test typeof(f2) !== typeof(f)
110-
111-
chicken_tikka_masala(y) = x -> x+y
112-
f = chicken_tikka_masala(5)
113-
f2 = BSON.roundtrip(f)
114-
@test f2(6) == f(6)
115-
@test typeof(f2) !== typeof(f)
116-
else
117-
@test_throws ErrorException f2 = BSON.roundtrip(f)
118-
end
127+
f2 = BSON.roundtrip(f)
128+
@test f2(5) == f(5)
129+
@test typeof(f2) !== typeof(f)
130+
131+
chicken_tikka_masala(y) = x -> x+y
132+
f = chicken_tikka_masala(5)
133+
f2 = BSON.roundtrip(f)
134+
@test f2(6) == f(6)
135+
@test typeof(f2) !== typeof(f)
119136
end
120137

121138
@testset "Int Literals in Type Params #41" begin

0 commit comments

Comments
 (0)