mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Fix keyword argument separation issues in Enumerator::Generator#each
This requires adding rb_proc_call_kw to pass the keyword flag.
This commit is contained in:
parent
dd2068ac8d
commit
37f9213f89
Notes:
git
2019-09-27 07:31:16 +09:00
4 changed files with 97 additions and 1 deletions
|
@ -1506,7 +1506,7 @@ generator_each(int argc, VALUE *argv, VALUE obj)
|
|||
rb_ary_cat(args, argv, argc);
|
||||
}
|
||||
|
||||
return rb_proc_call(ptr->proc, args);
|
||||
return rb_proc_call_kw(ptr->proc, args, RB_PASS_CALLED_KEYWORDS);
|
||||
}
|
||||
|
||||
/* Lazy Enumerator methods */
|
||||
|
|
|
@ -454,6 +454,7 @@ VALUE rb_block_lambda(void);
|
|||
VALUE rb_proc_new(rb_block_call_func_t, VALUE);
|
||||
VALUE rb_obj_is_proc(VALUE);
|
||||
VALUE rb_proc_call(VALUE, VALUE);
|
||||
VALUE rb_proc_call_kw(VALUE, VALUE, int);
|
||||
VALUE rb_proc_call_with_block(VALUE, int argc, const VALUE *argv, VALUE);
|
||||
VALUE rb_proc_call_with_block_kw(VALUE, int argc, const VALUE *argv, VALUE, int);
|
||||
int rb_proc_arity(VALUE);
|
||||
|
|
18
proc.c
18
proc.c
|
@ -934,6 +934,24 @@ check_argc(long argc)
|
|||
#define check_argc(argc) (argc)
|
||||
#endif
|
||||
|
||||
VALUE
|
||||
rb_proc_call_kw(VALUE self, VALUE args, int kw_splat)
|
||||
{
|
||||
VALUE vret;
|
||||
rb_proc_t *proc;
|
||||
VALUE v;
|
||||
int argc = check_argc(RARRAY_LEN(args));
|
||||
const VALUE *argv = RARRAY_CONST_PTR(args);
|
||||
GetProcPtr(self, proc);
|
||||
v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
|
||||
vret = rb_vm_invoke_proc(GET_EC(), proc, argc, argv,
|
||||
kw_splat, VM_BLOCK_HANDLER_NONE);
|
||||
rb_free_tmp_buffer(&v);
|
||||
RB_GC_GUARD(self);
|
||||
RB_GC_GUARD(args);
|
||||
return vret;
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_proc_call(VALUE self, VALUE args)
|
||||
{
|
||||
|
|
|
@ -841,6 +841,83 @@ class TestKeywordArguments < Test::Unit::TestCase
|
|||
assert_equal([1, h3], t.new(&f).resume(a: 1, **h2))
|
||||
end
|
||||
|
||||
def test_Enumerator_Generator_each_kwsplat
|
||||
kw = {}
|
||||
h = {:a=>1}
|
||||
h2 = {'a'=>1}
|
||||
h3 = {'a'=>1, :a=>1}
|
||||
|
||||
g = Enumerator::Generator
|
||||
f = ->(_) { true }
|
||||
assert_equal(true, g.new(&f).each(**{}))
|
||||
assert_equal(true, g.new(&f).each(**kw))
|
||||
assert_raise(ArgumentError) { g.new(&f).each(**h) }
|
||||
assert_raise(ArgumentError) { g.new(&f).each(a: 1) }
|
||||
assert_raise(ArgumentError) { g.new(&f).each(**h2) }
|
||||
assert_raise(ArgumentError) { g.new(&f).each(**h3) }
|
||||
|
||||
f = ->(_, a) { a }
|
||||
assert_warn(/The keyword argument is passed as the last hash parameter/m) do
|
||||
assert_equal(kw, g.new(&f).each(**{}))
|
||||
end
|
||||
assert_warn(/The keyword argument is passed as the last hash parameter/m) do
|
||||
assert_equal(kw, g.new(&f).each(**kw))
|
||||
end
|
||||
assert_equal(h, g.new(&f).each(**h))
|
||||
assert_equal(h, g.new(&f).each(a: 1))
|
||||
assert_equal(h2, g.new(&f).each(**h2))
|
||||
assert_equal(h3, g.new(&f).each(**h3))
|
||||
assert_equal(h3, g.new(&f).each(a: 1, **h2))
|
||||
|
||||
f = ->(_, **x) { x }
|
||||
assert_equal(kw, g.new(&f).each(**{}))
|
||||
assert_equal(kw, g.new(&f).each(**kw))
|
||||
assert_equal(h, g.new(&f).each(**h))
|
||||
assert_equal(h, g.new(&f).each(a: 1))
|
||||
assert_equal(h2, g.new(&f).each(**h2))
|
||||
assert_equal(h3, g.new(&f).each(**h3))
|
||||
assert_equal(h3, g.new(&f).each(a: 1, **h2))
|
||||
assert_warn(/The last argument is used as the keyword parameter.*for method/m) do
|
||||
assert_equal(h, g.new(&f).each(h))
|
||||
end
|
||||
assert_raise(ArgumentError) { g.new(&f).each(h2) }
|
||||
assert_warn(/The last argument is split into positional and keyword parameters.*for method/m) do
|
||||
assert_raise(ArgumentError) { g.new(&f).each(h3) }
|
||||
end
|
||||
|
||||
f = ->(_, a, **x) { [a,x] }
|
||||
assert_warn(/The keyword argument is passed as the last hash parameter/) do
|
||||
assert_equal([{}, {}], g.new(&f).each(**{}))
|
||||
end
|
||||
assert_warn(/The keyword argument is passed as the last hash parameter/) do
|
||||
assert_equal([{}, {}], g.new(&f).each(**kw))
|
||||
end
|
||||
assert_warn(/The keyword argument is passed as the last hash parameter/) do
|
||||
assert_equal([h, {}], g.new(&f).each(**h))
|
||||
end
|
||||
assert_warn(/The keyword argument is passed as the last hash parameter/) do
|
||||
assert_equal([h, {}], g.new(&f).each(a: 1))
|
||||
end
|
||||
assert_warn(/The keyword argument is passed as the last hash parameter/) do
|
||||
assert_equal([h2, {}], g.new(&f).each(**h2))
|
||||
end
|
||||
assert_warn(/The keyword argument is passed as the last hash parameter/) do
|
||||
assert_equal([h3, {}], g.new(&f).each(**h3))
|
||||
end
|
||||
assert_warn(/The keyword argument is passed as the last hash parameter/) do
|
||||
assert_equal([h3, {}], g.new(&f).each(a: 1, **h2))
|
||||
end
|
||||
|
||||
f = ->(_, a=1, **x) { [a, x] }
|
||||
assert_equal([1, kw], g.new(&f).each(**{}))
|
||||
assert_equal([1, kw], g.new(&f).each(**kw))
|
||||
assert_equal([1, h], g.new(&f).each(**h))
|
||||
assert_equal([1, h], g.new(&f).each(a: 1))
|
||||
assert_equal([1, h2], g.new(&f).each(**h2))
|
||||
assert_equal([1, h3], g.new(&f).each(**h3))
|
||||
assert_equal([1, h3], g.new(&f).each(a: 1, **h2))
|
||||
end
|
||||
|
||||
def test_Class_new_kwsplat_call
|
||||
kw = {}
|
||||
h = {:a=>1}
|
||||
|
|
Loading…
Add table
Reference in a new issue