Skip to content

Commit

Permalink
preserve identities of type wrappers in serializer. fixes #20324
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson committed Mar 25, 2017
1 parent bbbfa6c commit a33d30b
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 0 deletions.
44 changes: 44 additions & 0 deletions base/serialize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ const TYPENAME_TAG = sertag(TypeName)
const INT_TAG = sertag(Int)
const GLOBALREF_TAG = sertag(GlobalRef)
const BOTTOM_TAG = sertag(Bottom)
const UNIONALL_TAG = sertag(UnionAll)

writetag(s::IO, tag) = write(s, UInt8(tag))

Expand Down Expand Up @@ -518,6 +519,24 @@ end

serialize(s::AbstractSerializer, ::Type{Bottom}) = write_as_tag(s.io, BOTTOM_TAG)

function serialize(s::AbstractSerializer, u::UnionAll)
writetag(s.io, UNIONALL_TAG)
n = 0; t = u
while isa(t, UnionAll)
t = t.body
n += 1
end
if isa(t, DataType) && t === unwrap_unionall(t.name.wrapper)
write(s.io, UInt8(1))
write(s.io, Int16(n))
serialize(s, t)
else
write(s.io, UInt8(0))
serialize(s, u.var)
serialize(s, u.body)
end
end

serialize(s::AbstractSerializer, x::ANY) = serialize_any(s, x)

function serialize_any(s::AbstractSerializer, x::ANY)
Expand Down Expand Up @@ -857,6 +876,31 @@ function deserialize_datatype(s::AbstractSerializer)
deserialize(s, t)
end

function deserialize(s::AbstractSerializer, ::Type{UnionAll})
form = read(s.io, UInt8)
if form == 0
var = deserialize(s)
body = deserialize(s)
return UnionAll(var, body)
else
n = read(s.io, Int16)
t = deserialize(s)::DataType
w = t.name.wrapper
k = 0
while isa(w, UnionAll)
w = w.body
k += 1
end
w = t.name.wrapper
k -= n
while k > 0
w = w.body
k -= 1
end
return w
end
end

function deserialize(s::AbstractSerializer, ::Type{Task})
t = Task(()->nothing)
deserialize_cycle(s, t)
Expand Down
13 changes: 13 additions & 0 deletions test/serialize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -444,3 +444,16 @@ let a = ['T', 'e', 's', 't']
seek(f,0)
@test deserialize(f) ===
end

# issue #20324
struct T20324{T}
x::T
end
let x = T20324[T20324(1) for i = 1:2]
b = IOBuffer()
serialize(b, x)
seekstart(b)
y = deserialize(b)
@test isa(y,Vector{T20324})
@test y == x
end

0 comments on commit a33d30b

Please sign in to comment.