diff --git a/NEWS.md b/NEWS.md index 38c0ef5c93bdf..87637f3a9d4c0 100644 --- a/NEWS.md +++ b/NEWS.md @@ -55,8 +55,9 @@ Library improvements * New `Nullable` type for missing data ([#8152]). - * New ordschur and ordschur! functions for sorting a schur factorization by the eigenvalues + * New `ordschur` and `ordschur!` functions for sorting a schur factorization by the eigenvalues. + * `deepcopy` recurses through immutable types and makes copies of their mutable fields ([#8560]). Julia v0.3.0 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 7102958db9e0a..f02a30ee0a421 100644 --- a/doc/stdlib/base.rst +++ b/doc/stdlib/base.rst @@ -219,7 +219,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.