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

Always copy Hash's default block on #dup and #clone #10744

Merged
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
20 changes: 20 additions & 0 deletions spec/std/hash_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,16 @@ describe "Hash" do
clone = h.clone
clone.should be(clone.first[1])
end

it "retains default block on clone" do
h1 = Hash(Int32, String).new("a")
h2 = h1.clone
h2[0].should eq("a")

h1[1] = "b"
h3 = h1.clone
h3[0].should eq("a")
end
end

describe "dup" do
Expand Down Expand Up @@ -536,6 +546,16 @@ describe "Hash" do
h1.delete(0)
h2[0].should eq([0])
end

it "retains default block on dup" do
h1 = Hash(Int32, String).new("a")
h2 = h1.dup
h2[0].should eq("a")

h1[1] = "b"
h3 = h1.dup
h3[0].should eq("a")
end
end

it "initializes with block" do
Expand Down
9 changes: 7 additions & 2 deletions src/hash.cr
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,7 @@ class Hash(K, V)
# Initializes a `dup` copy from the contents of `other`.
protected def initialize_dup(other)
initialize_compare_by_identity(other)
initialize_default_block(other)

return if other.empty?

Expand All @@ -650,6 +651,7 @@ class Hash(K, V)
# Initializes a `clone` copy from the contents of `other`.
protected def initialize_clone(other)
initialize_compare_by_identity(other)
initialize_default_block(other)

return if other.empty?

Expand All @@ -661,6 +663,10 @@ class Hash(K, V)
compare_by_identity if other.compare_by_identity?
end

private def initialize_default_block(other)
@block = other.@block
end

# Initializes `@entries` for a dup copy.
# Here we only need to duplicate the buffer.
private def initialize_dup_entries(other)
Expand All @@ -685,14 +691,13 @@ class Hash(K, V)
end
end

# Initializes all variables other than `@entries` for a copy.
# Initializes all variables other than `@entries` and `@block` for a copy.
private def initialize_copy_non_entries_vars(other)
@indices_bytesize = other.@indices_bytesize
@first = other.@first
@size = other.@size
@deleted_count = other.@deleted_count
@indices_size_pow2 = other.@indices_size_pow2
@block = other.@block

unless other.@indices.null?
@indices = malloc_indices(other.indices_size)
Expand Down