Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deepcopy: recurse through immutable objects with mutable fields. #8560

Merged
merged 3 commits into from
Oct 3, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
==========================
Expand Down
23 changes: 13 additions & 10 deletions base/deepcopy.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
2 changes: 1 addition & 1 deletion doc/stdlib/base.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down