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)
|
baz(*args)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def pass_bar(*args)
|
||||||
|
bar(*args)
|
||||||
|
end
|
||||||
|
|
||||||
def bar(*args, **kw)
|
def bar(*args, **kw)
|
||||||
[args, kw]
|
[args, kw]
|
||||||
end
|
end
|
||||||
|
@ -2907,6 +2911,10 @@ class TestKeywordArguments < Test::Unit::TestCase
|
||||||
assert_equal([1, h1], o.baz(1, h1))
|
assert_equal([1, h1], o.baz(1, h1))
|
||||||
assert_equal([h1], o.baz(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_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))
|
assert_nil(c.send(:ruby2_keywords, :bar))
|
||||||
end
|
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 (!kw_flag && len > 0) {
|
||||||
if (RB_TYPE_P(rest_last, T_HASH) &&
|
if (RB_TYPE_P(rest_last, T_HASH) &&
|
||||||
(((struct RHash *)rest_last)->basic.flags & RHASH_PASS_AS_KEYWORDS)) {
|
(((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;
|
kw_flag |= VM_CALL_KW_SPLAT;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
Loading…
Add table
Reference in a new issue