mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Dup hash with keyword flag when converted to keywords
When ruby2_keywords is used on a method, keywords passed to the method are flagged. When the hash is passed as the last element of an argument splat to another method, the hash should be treated as a keyword splat. When keyword splatting a hash, a duplicate of the hash is made. So when auto-splatting the hash with the keyword flag, a duplicate of the hash should also be made. This fixes cases where the hash is later passed to another method and would be treated as keywords there: class Object ruby2_keywords def foo(*a) bar(*a) end def bar(*a) baz(*a) end def baz(*a, **kw) [a, kw] end end foo(:a=>1) Previously, this would pass the :a=>1 as keywords to bar and also as keywords to baz. Now it only passes :a=>1 as keywords to bar, but bar passes :a=>1 as a positional hash to baz (which in this case generates a warning in 2.7).
This commit is contained in:
parent
259601ab57
commit
6081ddd6e6
2 changed files with 10 additions and 0 deletions
|
@ -2664,6 +2664,10 @@ class TestKeywordArguments < Test::Unit::TestCase
|
|||
baz(*args)
|
||||
end
|
||||
|
||||
def pass_bar(*args)
|
||||
bar(*args)
|
||||
end
|
||||
|
||||
def bar(*args, **kw)
|
||||
[args, kw]
|
||||
end
|
||||
|
@ -2907,6 +2911,10 @@ class TestKeywordArguments < Test::Unit::TestCase
|
|||
assert_equal([1, h1], o.baz(1, h1))
|
||||
assert_equal([h1], o.baz(h1, **{}))
|
||||
|
||||
assert_warn(/The last argument is used as the keyword parameter.* for `bar'/m) do
|
||||
assert_equal([[1], h1], o.foo(:pass_bar, 1, :a=>1))
|
||||
end
|
||||
|
||||
assert_warn(/Skipping set of ruby2_keywords flag for bar \(method accepts keywords or method does not accept argument splat\)/) do
|
||||
assert_nil(c.send(:ruby2_keywords, :bar))
|
||||
end
|
||||
|
|
|
@ -737,6 +737,8 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
|
|||
if (!kw_flag && len > 0) {
|
||||
if (RB_TYPE_P(rest_last, T_HASH) &&
|
||||
(((struct RHash *)rest_last)->basic.flags & RHASH_PASS_AS_KEYWORDS)) {
|
||||
rest_last = rb_hash_dup(rest_last);
|
||||
RARRAY_ASET(args->rest, len - 1, rest_last);
|
||||
kw_flag |= VM_CALL_KW_SPLAT;
|
||||
}
|
||||
else {
|
||||
|
|
Loading…
Add table
Reference in a new issue