diff options
author | Jeremy Evans <code@jeremyevans.net> | 2019-10-15 12:46:24 -0700 |
---|---|---|
committer | Jeremy Evans <code@jeremyevans.net> | 2019-10-15 12:46:24 -0700 |
commit | 6081ddd6e6f2297862b3c7e898d28a76b8f9240b (patch) | |
tree | 4c2e563c0d6ce60dc26fe350fb4677eebceb3af8 /vm_args.c | |
parent | 259601ab578885418b36138e457c2a93dd281896 (diff) | |
download | ruby-6081ddd6e6f2297862b3c7e898d28a76b8f9240b.tar.gz |
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).
Diffstat (limited to 'vm_args.c')
-rw-r--r-- | vm_args.c | 2 |
1 files changed, 2 insertions, 0 deletions
@@ -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 { |