ruby-changes:65863
From: nagachika <ko1@a...>
Date: Thu, 15 Apr 2021 10:29:23 +0900 (JST)
Subject: [ruby-changes:65863] 84d9a9afc0 (ruby_3_0): merge revision(s) 31e0382723bfb35cffe3ca485dd0577668cafa07,5e5fb72f99701dc27c66ab148471893f14e6d6f0,fb6ebe55d91187d9635e0183d47dbf38e95b1141,522d4cd32f7727886f4fcbc28ed29c08d361ee20: [Backport #17735]
https://git.ruby-lang.org/ruby.git/commit/?id=84d9a9afc0 From 84d9a9afc0b49d095541acb9832f8b12fb506e19 Mon Sep 17 00:00:00 2001 From: nagachika <nagachika@r...> Date: Thu, 15 Apr 2021 10:11:19 +0900 Subject: merge revision(s) 31e0382723bfb35cffe3ca485dd0577668cafa07,5e5fb72f99701dc27c66ab148471893f14e6d6f0,fb6ebe55d91187d9635e0183d47dbf38e95b1141,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 https://github.com/ruby/ruby/pull/4329#issuecomment-808840718 --- hash.c | 2 ++ 1 file changed, 2 insertions(+) --- hash.c | 15 ++++++++++++--- spec/ruby/core/hash/transform_keys_spec.rb | 12 +++++++++++- test/ruby/test_hash.rb | 8 ++++++++ version.h | 2 +- 4 files changed, 32 insertions(+), 5 deletions(-) diff --git a/hash.c b/hash.c index 0ed2692..e29e985 100644 --- a/hash.c +++ b/hash.c @@ -3249,7 +3249,7 @@ rb_hash_transform_keys(int argc, VALUE *argv, VALUE hash) https://github.com/ruby/ruby/blob/trunk/hash.c#L3249 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: @@ -3278,8 +3278,9 @@ rb_hash_transform_keys_bang(int argc, VALUE *argv, VALUE hash) https://github.com/ruby/ruby/blob/trunk/hash.c#L3278 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; @@ -3296,8 +3297,16 @@ rb_hash_transform_keys_bang(int argc, VALUE *argv, VALUE hash) https://github.com/ruby/ruby/blob/trunk/hash.c#L3297 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; } diff --git a/spec/ruby/core/hash/transform_keys_spec.rb b/spec/ruby/core/hash/transform_keys_spec.rb index 2c5d412..55aec39 100644 --- a/spec/ruby/core/hash/transform_keys_spec.rb +++ b/spec/ruby/core/hash/transform_keys_spec.rb @@ -84,7 +84,7 @@ describe "Hash#transform_keys!" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/hash/transform_keys_spec.rb#L84 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 @@ -94,6 +94,16 @@ describe "Hash#transform_keys!" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/hash/transform_keys_spec.rb#L94 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 diff --git a/test/ruby/test_hash.rb b/test/ruby/test_hash.rb index 62d8b3f..812b9e6 100644 --- a/test/ruby/test_hash.rb +++ b/test/ruby/test_hash.rb @@ -1674,6 +1674,10 @@ class TestHash < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_hash.rb#L1674 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) @@ -1710,6 +1714,10 @@ class TestHash < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_hash.rb#L1714 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)) end diff --git a/version.h b/version.h index 41f7a51..899059b 100644 --- a/version.h +++ b/version.h @@ -12,7 +12,7 @@ https://github.com/ruby/ruby/blob/trunk/version.h#L12 # 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 -- cgit v1.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/