diff --git a/NEWS.md b/NEWS.md index a5627d4de5c25..4ef000c454e46 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,11 @@ +Julia v0.3.7 Release Notes +========================== + +Library improvements +-------------------- + + * `deepcopy` recurses through immutable types and makes copies of their mutable fields ([#8560]). + Julia v0.3.4 Release Notes ========================== diff --git a/base/deepcopy.jl b/base/deepcopy.jl index d96c36637c7a7..07e7add299cf2 100644 --- a/base/deepcopy.jl +++ b/base/deepcopy.jl @@ -27,20 +27,23 @@ function deepcopy_internal(x, stackdict::ObjectIdDict) end function _deepcopy_t(x, T::DataType, stackdict::ObjectIdDict) - if T.names===() || !T.mutable - return x - end - ret = ccall(:jl_new_struct_uninit, Any, (Any,), T) - stackdict[x] = ret - for i in 1:length(T.names) - if isdefined(x,i) - ret.(i) = deepcopy_internal(x.(i), stackdict) + isbits(T) | isempty(T.names) && return x + if T.mutable + y = ccall(:jl_new_struct_uninit, Any, (Any,), T) + stackdict[x] = y + for i in 1:length(T.names) + if isdefined(x,i) + y.(i) = deepcopy_internal(x.(i), stackdict) + end end + else + fields = Any[deepcopy_internal(x.(i), stackdict) for i in 1:length(T.names)] + y = ccall(:jl_new_structv, Any, (Any, Ptr{Void}, Uint32), + T, pointer(fields), length(fields)) end - return ret + return y::T end - function deepcopy_internal(x::Array, stackdict::ObjectIdDict) if haskey(stackdict, x) return stackdict[x] diff --git a/doc/stdlib/base.rst b/doc/stdlib/base.rst index dd1b55d34ca2d..bf2eaa42f73bc 100644 --- a/doc/stdlib/base.rst +++ b/doc/stdlib/base.rst @@ -217,7 +217,7 @@ All Objects .. function:: deepcopy(x) - Create a deep copy of ``x``: everything is copied recursively, resulting in a fully independent object. For example, deep-copying an array produces a new array whose elements are deep-copies of the original elements. + Create a deep copy of ``x``: everything is copied recursively, resulting in a fully independent object. For example, deep-copying an array produces a new array whose elements are deep copies of the original elements. Calling `deepcopy` on an object should generally have the same effect as serializing and then deserializing it. As a special case, functions can only be actually deep-copied if they are anonymous, otherwise they are just copied. The difference is only relevant in the case of closures, i.e. functions which may contain hidden internal references.