summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Evans <[email protected]>2023-07-10 10:06:23 -0700
committerGitHub <[email protected]>2023-07-10 10:06:23 -0700
commit3874381c4483ba7794ac2abf157e265546f9bfa7 (patch)
treed02850a4e81c80e44137c6cfc8c992a2538eb61d
parent53c560156542915938ebebeac3e12352c04feb24 (diff)
Fix autosplat conditions to handle ruby2_keywords case
Autosplat should not occur if there are two arguments but second argument is an array containing a ruby2_keywords splat. Only autosplat if a single argument to be yielded to the block, and there is no splatted flagged keyword hash passed. Fixes [Bug #19759]
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/8039 Merged-By: jeremyevans <[email protected]>
-rw-r--r--test/ruby/test_proc.rb26
-rw-r--r--vm_args.c3
2 files changed, 28 insertions, 1 deletions
diff --git a/test/ruby/test_proc.rb b/test/ruby/test_proc.rb
index 05c6e03aac..2b3590d4d0 100644
--- a/test/ruby/test_proc.rb
+++ b/test/ruby/test_proc.rb
@@ -1321,6 +1321,32 @@ class TestProc < Test::Unit::TestCase
assert_empty(pr.parameters.map{|_,n|n}.compact)
end
+ def test_proc_autosplat_with_multiple_args_with_ruby2_keywords_splat_bug_19759
+ def self.yielder_ab(splat)
+ yield([:a, :b], *splat)
+ end
+
+ res = yielder_ab([[:aa, :bb], Hash.ruby2_keywords_hash({k: :k})]) do |a, b, k:|
+ [a, b, k]
+ end
+ assert_equal([[:a, :b], [:aa, :bb], :k], res)
+
+ def self.yielder(splat)
+ yield(*splat)
+ end
+ res = yielder([ [:a, :b] ]){|a, b, **| [a, b]}
+ assert_equal([:a, :b], res)
+
+ res = yielder([ [:a, :b], Hash.ruby2_keywords_hash({}) ]){|a, b, **| [a, b]}
+ assert_equal([[:a, :b], nil], res)
+
+ res = yielder([ [:a, :b], Hash.ruby2_keywords_hash({c: 1}) ]){|a, b, **| [a, b]}
+ assert_equal([[:a, :b], nil], res)
+
+ res = yielder([ [:a, :b], Hash.ruby2_keywords_hash({}) ]){|a, b, **nil| [a, b]}
+ assert_equal([[:a, :b], nil], res)
+ end
+
def test_parameters_lambda
assert_equal([], proc {}.parameters(lambda: true))
assert_equal([], proc {||}.parameters(lambda: true))
diff --git a/vm_args.c b/vm_args.c
index cc7f1e29b5..6832849e1e 100644
--- a/vm_args.c
+++ b/vm_args.c
@@ -640,8 +640,9 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
case arg_setup_method:
break; /* do nothing special */
case arg_setup_block:
- if (given_argc == (NIL_P(keyword_hash) ? 1 : 2) &&
+ if (given_argc == 1 &&
allow_autosplat &&
+ !splat_flagged_keyword_hash &&
(min_argc > 0 || ISEQ_BODY(iseq)->param.opt_num > 1) &&
!ISEQ_BODY(iseq)->param.flags.ambiguous_param0 &&
!((ISEQ_BODY(iseq)->param.flags.has_kw ||