Skip to content

Commit

Permalink
merge revision(s) 31e0382,5e5fb72f99701dc27c66ab148471893f14e6d6f0,fb…
Browse files Browse the repository at this point in the history
…6ebe55d91187d9635e0183d47dbf38e95b1141,522d4cd32f7727886f4fcbc28ed29c08d361ee20: [Backport #17735]

	Keep non evaluated keys in `Hash#transform_keys!` [Bug #17735]

	---
	 hash.c                                     |  6 +++++-
	 spec/ruby/core/hash/transform_keys_spec.rb | 12 +++++++++++-
	 test/ruby/test_hash.rb                     |  8 ++++++++
	 3 files changed, 24 insertions(+), 2 deletions(-)

	Clear an intermediate hash [Bug #17735]

	---
	 hash.c | 1 +
	 1 file changed, 1 insertion(+)

	Hide an intermediate array

	---
	 hash.c | 6 ++++--
	 1 file changed, 4 insertions(+), 2 deletions(-)

	Force recycle intermediate collection in Hash#transform_keys! [Bug
	 #17735]

	* Force recycle intermediate hash

	* Force recycle intermediate array too

	#4329 (comment)
	---
	 hash.c | 2 ++
	 1 file changed, 2 insertions(+)
  • Loading branch information
nagachika committed Apr 15, 2021
1 parent d5a34e1 commit 84d9a9a
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 5 deletions.
15 changes: 12 additions & 3 deletions hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -3249,7 +3249,7 @@ rb_hash_transform_keys(int argc, VALUE *argv, VALUE hash)
return result;
}

static VALUE rb_hash_flatten(int argc, VALUE *argv, VALUE hash);
static int flatten_i(VALUE key, VALUE val, VALUE ary);

/*
* call-seq:
Expand Down Expand Up @@ -3278,8 +3278,9 @@ rb_hash_transform_keys_bang(int argc, VALUE *argv, VALUE hash)
rb_hash_modify_check(hash);
if (!RHASH_TABLE_EMPTY_P(hash)) {
long i;
VALUE pairs = rb_hash_flatten(0, NULL, hash);
rb_hash_clear(hash);
VALUE new_keys = hash_alloc(0);
VALUE pairs = rb_ary_tmp_new(RHASH_SIZE(hash) * 2);
rb_hash_foreach(hash, flatten_i, pairs);
for (i = 0; i < RARRAY_LEN(pairs); i += 2) {
VALUE key = RARRAY_AREF(pairs, i), new_key, val;

Expand All @@ -3296,8 +3297,16 @@ rb_hash_transform_keys_bang(int argc, VALUE *argv, VALUE hash)
new_key = key;
}
val = RARRAY_AREF(pairs, i+1);
if (!hash_stlike_lookup(new_keys, key, NULL)) {
rb_hash_stlike_delete(hash, &key, NULL);
}
rb_hash_aset(hash, new_key, val);
rb_hash_aset(new_keys, new_key, Qnil);
}
rb_ary_clear(pairs);
rb_gc_force_recycle(pairs);
rb_hash_clear(new_keys);
rb_gc_force_recycle(new_keys);
}
return hash;
}
Expand Down
12 changes: 11 additions & 1 deletion spec/ruby/core/hash/transform_keys_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
end
end

ruby_version_is "2.5.1" do
ruby_version_is "2.5.1"..."3.0" do
it "returns the processed keys if we broke from the block" do
@hash.transform_keys! do |v|
break if v == :c
Expand All @@ -94,6 +94,16 @@
end
end

ruby_version_is "3.0" do
it "returns the processed keys and non evaluated keys if we broke from the block" do
@hash.transform_keys! do |v|
break if v == :c
v.succ
end
@hash.should == { b: 1, c: 2, d: 4 }
end
end

it "keeps later pair if new keys conflict" do
@hash.transform_keys! { |_| :a }.should == { a: 4 }
end
Expand Down
8 changes: 8 additions & 0 deletions test/ruby/test_hash.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1674,6 +1674,10 @@ def test_transform_keys_bang
x.transform_keys! {|k| -k }
assert_equal([-1, :a, 1, :b], x.flatten)

x = @cls[a: 1, b: 2, c: 3]
x.transform_keys! { |k| k == :b && break }
assert_equal({false => 1, b: 2, c: 3}, x)

x = @cls[true => :a, false => :b]
x.transform_keys! {|k| !k }
assert_equal([false, :a, true, :b], x.flatten)
Expand Down Expand Up @@ -1709,6 +1713,10 @@ def test_transform_values_bang
assert_equal([1, 4, 9], y.values_at(:a, :b, :c))
assert_same(x, y)

x = @cls[a: 1, b: 2, c: 3]
x.transform_values! { |v| v == 2 && break }
assert_equal({a: false, b: 2, c: 3}, x)

x = @cls[a: 1, b: 2, c: 3]
y = x.transform_values!.with_index {|v, i| "#{v}.#{i}" }
assert_equal(%w(1.0 2.1 3.2), y.values_at(:a, :b, :c))
Expand Down
2 changes: 1 addition & 1 deletion version.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
#define RUBY_VERSION_TEENY 2
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
#define RUBY_PATCHLEVEL 66
#define RUBY_PATCHLEVEL 67

#define RUBY_RELEASE_YEAR 2021
#define RUBY_RELEASE_MONTH 4
Expand Down

0 comments on commit 84d9a9a

Please sign in to comment.