[前][次][番号順一覧][スレッド一覧]

ruby-changes:57628

From: Jeremy <ko1@a...>
Date: Sat, 7 Sep 2019 11:50:14 +0900 (JST)
Subject: [ruby-changes:57628] 80e679ef2d (master): Fix keyword argument separation warnings for enumerators

https://git.ruby-lang.org/ruby.git/commit/?id=80e679ef2d

From 80e679ef2d6f370e853e37053c73930c65b5e76c Mon Sep 17 00:00:00 2001
From: Jeremy Evans <code@j...>
Date: Fri, 6 Sep 2019 13:33:19 -0700
Subject: 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.

diff --git a/enumerator.c b/enumerator.c
index a8d14bb..e6f86c2 100644
--- a/enumerator.c
+++ b/enumerator.c
@@ -135,6 +135,7 @@ struct enumerator { https://github.com/ruby/ruby/blob/trunk/enumerator.c#L135
     VALUE size;
     VALUE procs;
     rb_enumerator_size_func *size_fn;
+    int kw_splat;
 };
 
 static VALUE rb_cGenerator, rb_cYielder;
@@ -364,8 +365,10 @@ enumerator_allocate(VALUE klass) https://github.com/ruby/ruby/blob/trunk/enumerator.c#L365
     return enum_obj;
 }
 
+#define PASS_KW_SPLAT (rb_empty_keyword_given_p() ? 2 : rb_keyword_given_p())
+
 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;
 
@@ -378,7 +381,13 @@ enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, const VALUE *ar https://github.com/ruby/ruby/blob/trunk/enumerator.c#L381
 
     ptr->obj  = obj;
     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->dst = Qnil;
     ptr->lookahead = Qundef;
@@ -386,6 +395,7 @@ enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, const VALUE *ar https://github.com/ruby/ruby/blob/trunk/enumerator.c#L395
     ptr->stop_exc = Qfalse;
     ptr->size = size;
     ptr->size_fn = size_fn;
+    ptr->kw_splat = kw_splat;
 
     return enum_obj;
 }
@@ -433,6 +443,7 @@ enumerator_initialize(int argc, VALUE *argv, VALUE obj) https://github.com/ruby/ruby/blob/trunk/enumerator.c#L443
 {
     VALUE recv, meth = sym_each;
     VALUE size = Qnil;
+    int kw_splat = 0;
 
     if (rb_block_given_p()) {
 	rb_check_arity(argc, 0, 1);
@@ -456,9 +467,10 @@ enumerator_initialize(int argc, VALUE *argv, VALUE obj) https://github.com/ruby/ruby/blob/trunk/enumerator.c#L467
 	    meth = *argv++;
 	    --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: */
@@ -513,7 +525,7 @@ rb_enumeratorize_with_size(VALUE obj, VALUE meth, int argc, const VALUE *argv, r https://github.com/ruby/ruby/blob/trunk/enumerator.c#L525
 	return lazy_to_enum_i(obj, meth, argc, argv, size_fn);
     else
 	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
@@ -528,7 +540,7 @@ enumerator_block_call(VALUE obj, rb_block_call_func *func, VALUE arg) https://github.com/ruby/ruby/blob/trunk/enumerator.c#L540
 	argc = RARRAY_LENINT(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) https://github.com/ruby/ruby/blob/trunk/enumerator.c#L1754
     }
     generator = generator_allocate(rb_cGenerator);
     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);
 
     return self;
@@ -1867,7 +1879,7 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/enumerator.c#L1879
 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),
-			   obj, meth, argc, argv, size_fn, Qnil);
+                           obj, meth, argc, argv, size_fn, Qnil, PASS_KW_SPLAT);
 }
 
 /*
@@ -1929,7 +1941,7 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/enumerator.c#L1941
 lazy_eager(VALUE self)
 {
     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
@@ -3054,7 +3066,7 @@ rb_arith_seq_new(VALUE obj, VALUE meth, int argc, VALUE const *argv, https://github.com/ruby/ruby/blob/trunk/enumerator.c#L3066
                  VALUE beg, VALUE end, VALUE step, int excl)
 {
     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_end, end);
     rb_ivar_set(aseq, id_step, step);
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index 1e4bafc..445b2cd 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -1967,6 +1967,7 @@ int rb_block_given_p(void); https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L1967
 void rb_need_block(void);
 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_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_rescue2(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE,VALUE),VALUE,...);
 VALUE rb_vrescue2(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE,VALUE),VALUE,va_list);
diff --git a/vm_eval.c b/vm_eval.c
index 4a3b9e3..e8e12bc 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -1277,6 +1277,7 @@ struct iter_method_arg { https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L1277
     ID mid;
     int argc;
     const VALUE *argv;
+    int kw_splat;
 };
 
 static VALUE
@@ -1285,7 +1286,7 @@ iterate_method(VALUE obj) https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L1286
     const struct iter_method_arg * arg =
       (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
@@ -1298,6 +1299,21 @@ rb_block_call(VALUE obj, ID mid, int argc, const VALUE * argv, https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L1299
     arg.mid = mid;
     arg.argc = argc;
     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);
 }
 
@@ -1314,6 +1330,7 @@ rb_lambda_call(VALUE obj, ID mid, int argc, const VALUE *argv, https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L1330
     arg.mid = mid;
     arg.argc = argc;
     arg.argv = argv;
+    arg.kw_splat = 0;
     block = rb_vm_ifunc_new(bl_proc, (void *)data2, min_argc, max_argc);
     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, https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L1354
     arg.mid = mid;
     arg.argc = argc;
     arg.argv = argv;
+    arg.kw_splat = 0;
     return rb_iterate(iterate_check_method, (VALUE)&arg, bl_proc, data2);
 }
 
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]