diff --git a/CHANGELOG.md b/CHANGELOG.md index 3abbd17d041d..6b5f06711d78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ Compatibility: * `Module#attr_*` methods now return an array of method names (#2498, @gogainda). * Fixed `Socket#(local|remote)_address` to retrieve family and type from the file descriptor (#2444, @larskanis). * Add `Thread.ignore_deadlock` accessor (#2453). +* Allow `Hash#transform_keys` to take a hash argument (@ccocchi, #2464). Performance: diff --git a/spec/tags/core/hash/transform_keys_tags.txt b/spec/tags/core/hash/transform_keys_tags.txt index 979402633bb8..897d63823eb4 100644 --- a/spec/tags/core/hash/transform_keys_tags.txt +++ b/spec/tags/core/hash/transform_keys_tags.txt @@ -1,6 +1 @@ fails:Hash#transform_keys! returns the processed keys and non evaluated keys if we broke from the block -fails:Hash#transform_keys allows a hash argument -fails:Hash#transform_keys allows a partial transformation of keys when using a hash argument -fails:Hash#transform_keys allows a combination of hash and block argument -fails:Hash#transform_keys! allows a hash argument -fails:Hash#transform_keys! on frozen instance raises a FrozenError on hash argument diff --git a/src/main/ruby/truffleruby/core/hash.rb b/src/main/ruby/truffleruby/core/hash.rb index 32fbe06eb62a..1f35548162dc 100644 --- a/src/main/ruby/truffleruby/core/hash.rb +++ b/src/main/ruby/truffleruby/core/hash.rb @@ -539,25 +539,47 @@ def transform_values! self end - def transform_keys - return to_enum(:transform_keys) { size } unless block_given? - + def transform_keys(mapping = nil) + has_block = block_given? h = {} - each_pair do |key, value| - h[yield(key)] = value + + if mapping + mapping = Truffle::Type.coerce_to(mapping, Hash, :to_hash) + each_pair do |key, value| + k = Primitive.hash_get_or_undefined(mapping, key) + k = has_block ? yield(key) : key if Primitive.undefined?(k) + h[k] = value + end + else + return to_enum(:transform_keys) { size } unless has_block + + each_pair do |key, value| + h[yield(key)] = value + end end + h end - def transform_keys! - return to_enum(:transform_keys!) { size } unless block_given? + def transform_keys!(mapping = nil) + has_block = block_given? + return to_enum(:transform_keys!) { size } unless mapping || has_block Primitive.check_frozen self - h = {} + begin - each_pair do |key, value| - h[yield(key)] = value + if mapping + mapping = Truffle::Type.coerce_to(mapping, Hash, :to_hash) + each_pair do |key, value| + k = Primitive.hash_get_or_undefined(mapping, key) + k = has_block ? yield(key) : key if Primitive.undefined?(k) + h[k] = value + end + else + each_pair do |key, value| + h[yield(key)] = value + end end ensure replace h diff --git a/tool/jt.rb b/tool/jt.rb index 4941d461f473..784b3c48cdc2 100755 --- a/tool/jt.rb +++ b/tool/jt.rb @@ -1637,9 +1637,6 @@ def purge(path, *args) def untag(path, *args) require_ruby_launcher! - puts - puts "WARNING: untag is currently not very reliable - run `jt test #{[path,*args] * ' '}` after and manually annotate any new failures" - puts test_specs('untag', path, *args) end