mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Fix keyword argument separation warnings for enumerators
This makes objects created via #to_enum and related methods pass keyword arguments as keywords. To implement this, add a kw_splat member of struct enumerator and struct iter_method_arg, and add rb_block_call_kw, which is the same as rb_block_call_kw with a flag for whether the last argument is keyword options.
This commit is contained in:
parent
37a2c660aa
commit
80e679ef2d
Notes:
git
2019-09-07 11:41:46 +09:00
3 changed files with 41 additions and 10 deletions
30
enumerator.c
30
enumerator.c
|
@ -135,6 +135,7 @@ struct enumerator {
|
||||||
VALUE size;
|
VALUE size;
|
||||||
VALUE procs;
|
VALUE procs;
|
||||||
rb_enumerator_size_func *size_fn;
|
rb_enumerator_size_func *size_fn;
|
||||||
|
int kw_splat;
|
||||||
};
|
};
|
||||||
|
|
||||||
static VALUE rb_cGenerator, rb_cYielder;
|
static VALUE rb_cGenerator, rb_cYielder;
|
||||||
|
@ -364,8 +365,10 @@ enumerator_allocate(VALUE klass)
|
||||||
return enum_obj;
|
return enum_obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define PASS_KW_SPLAT (rb_empty_keyword_given_p() ? 2 : rb_keyword_given_p())
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *size_fn, VALUE size)
|
enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *size_fn, VALUE size, int kw_splat)
|
||||||
{
|
{
|
||||||
struct enumerator *ptr;
|
struct enumerator *ptr;
|
||||||
|
|
||||||
|
@ -378,7 +381,13 @@ enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, const VALUE *ar
|
||||||
|
|
||||||
ptr->obj = obj;
|
ptr->obj = obj;
|
||||||
ptr->meth = rb_to_id(meth);
|
ptr->meth = rb_to_id(meth);
|
||||||
if (argc) ptr->args = rb_ary_new4(argc, argv);
|
if (kw_splat == 2) {
|
||||||
|
if (argc) ptr->args = rb_ary_new4(argc+1, rb_add_empty_keyword(argc, argv));
|
||||||
|
else ptr->args = rb_ary_new_from_args(1, rb_hash_new());
|
||||||
|
kw_splat = 1;
|
||||||
|
} else {
|
||||||
|
if (argc) ptr->args = rb_ary_new4(argc, argv);
|
||||||
|
}
|
||||||
ptr->fib = 0;
|
ptr->fib = 0;
|
||||||
ptr->dst = Qnil;
|
ptr->dst = Qnil;
|
||||||
ptr->lookahead = Qundef;
|
ptr->lookahead = Qundef;
|
||||||
|
@ -386,6 +395,7 @@ enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, const VALUE *ar
|
||||||
ptr->stop_exc = Qfalse;
|
ptr->stop_exc = Qfalse;
|
||||||
ptr->size = size;
|
ptr->size = size;
|
||||||
ptr->size_fn = size_fn;
|
ptr->size_fn = size_fn;
|
||||||
|
ptr->kw_splat = kw_splat;
|
||||||
|
|
||||||
return enum_obj;
|
return enum_obj;
|
||||||
}
|
}
|
||||||
|
@ -433,6 +443,7 @@ enumerator_initialize(int argc, VALUE *argv, VALUE obj)
|
||||||
{
|
{
|
||||||
VALUE recv, meth = sym_each;
|
VALUE recv, meth = sym_each;
|
||||||
VALUE size = Qnil;
|
VALUE size = Qnil;
|
||||||
|
int kw_splat = 0;
|
||||||
|
|
||||||
if (rb_block_given_p()) {
|
if (rb_block_given_p()) {
|
||||||
rb_check_arity(argc, 0, 1);
|
rb_check_arity(argc, 0, 1);
|
||||||
|
@ -456,9 +467,10 @@ enumerator_initialize(int argc, VALUE *argv, VALUE obj)
|
||||||
meth = *argv++;
|
meth = *argv++;
|
||||||
--argc;
|
--argc;
|
||||||
}
|
}
|
||||||
|
kw_splat = PASS_KW_SPLAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return enumerator_init(obj, recv, meth, argc, argv, 0, size);
|
return enumerator_init(obj, recv, meth, argc, argv, 0, size, kw_splat);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* :nodoc: */
|
/* :nodoc: */
|
||||||
|
@ -513,7 +525,7 @@ rb_enumeratorize_with_size(VALUE obj, VALUE meth, int argc, const VALUE *argv, r
|
||||||
return lazy_to_enum_i(obj, meth, argc, argv, size_fn);
|
return lazy_to_enum_i(obj, meth, argc, argv, size_fn);
|
||||||
else
|
else
|
||||||
return enumerator_init(enumerator_allocate(rb_cEnumerator),
|
return enumerator_init(enumerator_allocate(rb_cEnumerator),
|
||||||
obj, meth, argc, argv, size_fn, Qnil);
|
obj, meth, argc, argv, size_fn, Qnil, PASS_KW_SPLAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
|
@ -528,7 +540,7 @@ enumerator_block_call(VALUE obj, rb_block_call_func *func, VALUE arg)
|
||||||
argc = RARRAY_LENINT(e->args);
|
argc = RARRAY_LENINT(e->args);
|
||||||
argv = RARRAY_CONST_PTR(e->args);
|
argv = RARRAY_CONST_PTR(e->args);
|
||||||
}
|
}
|
||||||
return rb_block_call(e->obj, meth, argc, argv, func, arg);
|
return rb_block_call_kw(e->obj, meth, argc, argv, func, arg, e->kw_splat);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1742,7 +1754,7 @@ lazy_initialize(int argc, VALUE *argv, VALUE self)
|
||||||
}
|
}
|
||||||
generator = generator_allocate(rb_cGenerator);
|
generator = generator_allocate(rb_cGenerator);
|
||||||
rb_block_call(generator, id_initialize, 0, 0, lazy_init_block_i, obj);
|
rb_block_call(generator, id_initialize, 0, 0, lazy_init_block_i, obj);
|
||||||
enumerator_init(self, generator, sym_each, 0, 0, 0, size);
|
enumerator_init(self, generator, sym_each, 0, 0, 0, size, 0);
|
||||||
rb_ivar_set(self, id_receiver, obj);
|
rb_ivar_set(self, id_receiver, obj);
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
@ -1867,7 +1879,7 @@ static VALUE
|
||||||
lazy_to_enum_i(VALUE obj, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *size_fn)
|
lazy_to_enum_i(VALUE obj, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *size_fn)
|
||||||
{
|
{
|
||||||
return enumerator_init(enumerator_allocate(rb_cLazy),
|
return enumerator_init(enumerator_allocate(rb_cLazy),
|
||||||
obj, meth, argc, argv, size_fn, Qnil);
|
obj, meth, argc, argv, size_fn, Qnil, PASS_KW_SPLAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1929,7 +1941,7 @@ static VALUE
|
||||||
lazy_eager(VALUE self)
|
lazy_eager(VALUE self)
|
||||||
{
|
{
|
||||||
return enumerator_init(enumerator_allocate(rb_cEnumerator),
|
return enumerator_init(enumerator_allocate(rb_cEnumerator),
|
||||||
self, sym_each, 0, 0, lazy_eager_size, Qnil);
|
self, sym_each, 0, 0, lazy_eager_size, Qnil, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
|
@ -3054,7 +3066,7 @@ rb_arith_seq_new(VALUE obj, VALUE meth, int argc, VALUE const *argv,
|
||||||
VALUE beg, VALUE end, VALUE step, int excl)
|
VALUE beg, VALUE end, VALUE step, int excl)
|
||||||
{
|
{
|
||||||
VALUE aseq = enumerator_init(enumerator_allocate(rb_cArithSeq),
|
VALUE aseq = enumerator_init(enumerator_allocate(rb_cArithSeq),
|
||||||
obj, meth, argc, argv, size_fn, Qnil);
|
obj, meth, argc, argv, size_fn, Qnil, PASS_KW_SPLAT);
|
||||||
rb_ivar_set(aseq, id_begin, beg);
|
rb_ivar_set(aseq, id_begin, beg);
|
||||||
rb_ivar_set(aseq, id_end, end);
|
rb_ivar_set(aseq, id_end, end);
|
||||||
rb_ivar_set(aseq, id_step, step);
|
rb_ivar_set(aseq, id_step, step);
|
||||||
|
|
|
@ -1967,6 +1967,7 @@ int rb_block_given_p(void);
|
||||||
void rb_need_block(void);
|
void rb_need_block(void);
|
||||||
VALUE rb_iterate(VALUE(*)(VALUE),VALUE,rb_block_call_func_t,VALUE);
|
VALUE rb_iterate(VALUE(*)(VALUE),VALUE,rb_block_call_func_t,VALUE);
|
||||||
VALUE rb_block_call(VALUE,ID,int,const VALUE*,rb_block_call_func_t,VALUE);
|
VALUE rb_block_call(VALUE,ID,int,const VALUE*,rb_block_call_func_t,VALUE);
|
||||||
|
VALUE rb_block_call_kw(VALUE,ID,int,const VALUE*,rb_block_call_func_t,VALUE,int);
|
||||||
VALUE rb_rescue(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE,VALUE),VALUE);
|
VALUE rb_rescue(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE,VALUE),VALUE);
|
||||||
VALUE rb_rescue2(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE,VALUE),VALUE,...);
|
VALUE rb_rescue2(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE,VALUE),VALUE,...);
|
||||||
VALUE rb_vrescue2(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE,VALUE),VALUE,va_list);
|
VALUE rb_vrescue2(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE,VALUE),VALUE,va_list);
|
||||||
|
|
20
vm_eval.c
20
vm_eval.c
|
@ -1277,6 +1277,7 @@ struct iter_method_arg {
|
||||||
ID mid;
|
ID mid;
|
||||||
int argc;
|
int argc;
|
||||||
const VALUE *argv;
|
const VALUE *argv;
|
||||||
|
int kw_splat;
|
||||||
};
|
};
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
|
@ -1285,7 +1286,7 @@ iterate_method(VALUE obj)
|
||||||
const struct iter_method_arg * arg =
|
const struct iter_method_arg * arg =
|
||||||
(struct iter_method_arg *) obj;
|
(struct iter_method_arg *) obj;
|
||||||
|
|
||||||
return rb_call(arg->obj, arg->mid, arg->argc, arg->argv, CALL_FCALL);
|
return rb_call(arg->obj, arg->mid, arg->argc, arg->argv, arg->kw_splat ? CALL_FCALL_KW : CALL_FCALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
|
@ -1298,6 +1299,21 @@ rb_block_call(VALUE obj, ID mid, int argc, const VALUE * argv,
|
||||||
arg.mid = mid;
|
arg.mid = mid;
|
||||||
arg.argc = argc;
|
arg.argc = argc;
|
||||||
arg.argv = argv;
|
arg.argv = argv;
|
||||||
|
arg.kw_splat = 0;
|
||||||
|
return rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2);
|
||||||
|
}
|
||||||
|
|
||||||
|
VALUE
|
||||||
|
rb_block_call_kw(VALUE obj, ID mid, int argc, const VALUE * argv,
|
||||||
|
rb_block_call_func_t bl_proc, VALUE data2, int kw_splat)
|
||||||
|
{
|
||||||
|
struct iter_method_arg arg;
|
||||||
|
|
||||||
|
arg.obj = obj;
|
||||||
|
arg.mid = mid;
|
||||||
|
arg.argc = argc;
|
||||||
|
arg.argv = argv;
|
||||||
|
arg.kw_splat = kw_splat;
|
||||||
return rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2);
|
return rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1314,6 +1330,7 @@ rb_lambda_call(VALUE obj, ID mid, int argc, const VALUE *argv,
|
||||||
arg.mid = mid;
|
arg.mid = mid;
|
||||||
arg.argc = argc;
|
arg.argc = argc;
|
||||||
arg.argv = argv;
|
arg.argv = argv;
|
||||||
|
arg.kw_splat = 0;
|
||||||
block = rb_vm_ifunc_new(bl_proc, (void *)data2, min_argc, max_argc);
|
block = rb_vm_ifunc_new(bl_proc, (void *)data2, min_argc, max_argc);
|
||||||
return rb_iterate0(iterate_method, (VALUE)&arg, block, GET_EC());
|
return rb_iterate0(iterate_method, (VALUE)&arg, block, GET_EC());
|
||||||
}
|
}
|
||||||
|
@ -1337,6 +1354,7 @@ rb_check_block_call(VALUE obj, ID mid, int argc, const VALUE *argv,
|
||||||
arg.mid = mid;
|
arg.mid = mid;
|
||||||
arg.argc = argc;
|
arg.argc = argc;
|
||||||
arg.argv = argv;
|
arg.argv = argv;
|
||||||
|
arg.kw_splat = 0;
|
||||||
return rb_iterate(iterate_check_method, (VALUE)&arg, bl_proc, data2);
|
return rb_iterate(iterate_check_method, (VALUE)&arg, bl_proc, data2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue