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
@ -1506,7 +1506,7 @@ generator_each(int argc, VALUE *argv, VALUE obj)
|
|||||||
rb_ary_cat(args, argv, argc);
|
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 */
|
/* Lazy Enumerator methods */
|
||||||
|
@ -454,6 +454,7 @@ VALUE rb_block_lambda(void);
|
|||||||
VALUE rb_proc_new(rb_block_call_func_t, VALUE);
|
VALUE rb_proc_new(rb_block_call_func_t, VALUE);
|
||||||
VALUE rb_obj_is_proc(VALUE);
|
VALUE rb_obj_is_proc(VALUE);
|
||||||
VALUE rb_proc_call(VALUE, 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(VALUE, int argc, const VALUE *argv, VALUE);
|
||||||
VALUE rb_proc_call_with_block_kw(VALUE, int argc, const VALUE *argv, VALUE, int);
|
VALUE rb_proc_call_with_block_kw(VALUE, int argc, const VALUE *argv, VALUE, int);
|
||||||
int rb_proc_arity(VALUE);
|
int rb_proc_arity(VALUE);
|
||||||
|
18
proc.c
18
proc.c
@ -934,6 +934,24 @@ check_argc(long argc)
|
|||||||
#define check_argc(argc) (argc)
|
#define check_argc(argc) (argc)
|
||||||
#endif
|
#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
|
VALUE
|
||||||
rb_proc_call(VALUE self, VALUE args)
|
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))
|
assert_equal([1, h3], t.new(&f).resume(a: 1, **h2))
|
||||||
end
|
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
|
def test_Class_new_kwsplat_call
|
||||||
kw = {}
|
kw = {}
|
||||||
h = {:a=>1}
|
h = {:a=>1}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user