summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2019-11-27 09:03:00 -0800
committerJeremy Evans <code@jeremyevans.net>2019-11-27 20:03:27 +0200
commit299a13612e54accd9d3661bafde8f67142a78d54 (patch)
tree7582306ee4cdc1380e1789dcd466605bc0a57e5d
parent6f27fa4f7d52bfaea4fd1bd7605bda28e302e74c (diff)
Don't modify rest array when using ruby2_keywords
Previously, the rest array was modified, but it turns out that is not necessary. Not modifying the rest array fixes cases when the rest array is used more than once.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/2706
-rw-r--r--test/ruby/test_keyword.rb9
-rw-r--r--vm_args.c3
2 files changed, 10 insertions, 2 deletions
diff --git a/test/ruby/test_keyword.rb b/test/ruby/test_keyword.rb
index bbb107dedd..29335a4963 100644
--- a/test/ruby/test_keyword.rb
+++ b/test/ruby/test_keyword.rb
@@ -2649,6 +2649,11 @@ class TestKeywordArguments < Test::Unit::TestCase
baz(*args)
end
+ ruby2_keywords def foo_baz2(*args)
+ baz(*args)
+ baz(*args)
+ end
+
ruby2_keywords def foo_foo_bar(meth, *args)
foo_bar(meth, *args)
end
@@ -2761,6 +2766,10 @@ class TestKeywordArguments < Test::Unit::TestCase
h1 = {a: 1}
o = c.new
+ assert_equal([1, h1], o.foo_baz2(1, :a=>1))
+ assert_equal([1], o.foo_baz2(1, **{}))
+ assert_equal([h1], o.foo_baz2(h1, **{}))
+
assert_equal([[1], h1], o.foo(:bar, 1, :a=>1))
assert_equal([1, h1], o.foo(:baz, 1, :a=>1))
assert_equal([[1], h1], o.bfoo(:bar, 1, :a=>1))
diff --git a/vm_args.c b/vm_args.c
index 78a0f0dfbe..6729d54af7 100644
--- a/vm_args.c
+++ b/vm_args.c
@@ -742,7 +742,6 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
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;
if (iseq->body->param.flags.ruby2_keywords) {
remove_empty_keyword_hash = 0;
@@ -754,7 +753,7 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
}
if (kw_flag & VM_CALL_KW_SPLAT) {
- if (len > 0 && ignore_keyword_hash_p(RARRAY_AREF(args->rest, len - 1), iseq)) {
+ if (len > 0 && ignore_keyword_hash_p(rest_last, iseq)) {
if (given_argc != min_argc) {
if (remove_empty_keyword_hash) {
arg_rest_dup(args);