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

ruby-changes:58417

From: Nobuyoshi <ko1@a...>
Date: Fri, 25 Oct 2019 01:44:25 +0900 (JST)
Subject: [ruby-changes:58417] b609bdeb53 (master): Define arguments forwarding as `ruby2_keywords` style

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

From b609bdeb5307e280137b4b2838af0fe4e4b46f1c Mon Sep 17 00:00:00 2001
From: Nobuyoshi Nakada <nobu@r...>
Date: Fri, 25 Oct 2019 01:16:05 +0900
Subject: Define arguments forwarding as `ruby2_keywords` style

Get rid of these redundant and useless warnings.

```
$ ruby -e 'def bar(a) a; end; def foo(...) bar(...) end; foo({})'
-e:1: warning: The last argument is used as the keyword parameter
-e:1: warning: for `foo' defined here
-e:1: warning: The keyword argument is passed as the last hash parameter
-e:1: warning: for `bar' defined here
```

diff --git a/compile.c b/compile.c
index 0440ec5..278736d 100644
--- a/compile.c
+++ b/compile.c
@@ -1650,6 +1650,7 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, const NODE *cons https://github.com/ruby/ruby/blob/trunk/compile.c#L1650
 
 	EXPECT_NODE("iseq_set_arguments", node_args, NODE_ARGS, COMPILE_NG);
 
+        body->param.flags.ruby2_keywords = args->ruby2_keywords;
 	body->param.lead_num = arg_size = (int)args->pre_args_num;
 	if (body->param.lead_num > 0) body->param.flags.has_lead = TRUE;
 	debugs("  - argc: %d\n", body->param.lead_num);
diff --git a/node.h b/node.h
index 55c2984..8f43f45 100644
--- a/node.h
+++ b/node.h
@@ -453,7 +453,9 @@ struct rb_args_info { https://github.com/ruby/ruby/blob/trunk/node.h#L453
     NODE *kw_rest_arg;
 
     NODE *opt_args;
-    int no_kwarg;
+    unsigned int no_kwarg: 1;
+    unsigned int ruby2_keywords: 1;
+
     VALUE imemo;
 };
 
diff --git a/parse.y b/parse.y
index c3e385e..e7fcffa 100644
--- a/parse.y
+++ b/parse.y
@@ -598,7 +598,11 @@ static void numparam_pop(struct parser_params *p, NODE *prev_inner); https://github.com/ruby/ruby/blob/trunk/parse.y#L598
 #endif
 
 #define idFWD_REST   '*'
+#ifdef RUBY3_KEYWORDS
 #define idFWD_KWREST idPow /* Use simple "**", as tDSTAR is "**arg" */
+#else
+#define idFWD_KWREST 0
+#endif
 #define idFWD_BLOCK  '&'
 
 #define RE_OPTION_ONCE (1<<16)
@@ -2412,16 +2416,26 @@ paren_args	: '(' opt_call_args rparen https://github.com/ruby/ruby/blob/trunk/parse.y#L2416
 		    }
 		| '(' args_forward rparen
 		    {
-			if (!local_id(p, idFWD_REST) || !local_id(p, idFWD_KWREST) || !local_id(p, idFWD_BLOCK)) {
+			if (!local_id(p, idFWD_REST) ||
+#if idFWD_KWREST
+			    !local_id(p, idFWD_KWREST) ||
+#endif
+			    !local_id(p, idFWD_BLOCK)) {
 			    compile_error(p, "unexpected ...");
 			    $$ = Qnone;
 			}
 			else {
 			/*%%%*/
 			    NODE *splat = NEW_SPLAT(NEW_LVAR(idFWD_REST, &@2), &@2);
+#if idFWD_KWREST
 			    NODE *kwrest = list_append(p, NEW_LIST(0, &@2), NEW_LVAR(idFWD_KWREST, &@2));
+#endif
 			    NODE *block = NEW_BLOCK_PASS(NEW_LVAR(idFWD_BLOCK, &@2), &@2);
+#if idFWD_KWREST
 			    $$ = arg_append(p, splat, new_hash(p, kwrest, &@2), &@2);
+#else
+			    $$ = splat;
+#endif
 			    $$ = arg_blk_pass($$, block);
 			/*% %*/
 			/*% ripper: arg_paren!($2) %*/
@@ -4784,7 +4798,9 @@ f_arglist	: '(' f_args rparen https://github.com/ruby/ruby/blob/trunk/parse.y#L4798
 		| '(' args_forward rparen
 		    {
 			arg_var(p, idFWD_REST);
+#if idFWD_KWREST
 			arg_var(p, idFWD_KWREST);
+#endif
 			arg_var(p, idFWD_BLOCK);
 		    /*%%%*/
 			$$ = new_args_tail(p, Qnone, idFWD_KWREST, idFWD_BLOCK, &@2);
@@ -11257,6 +11273,8 @@ new_args(struct parser_params *p, NODE *pre_args, NODE *opt_args, ID rest_arg, N https://github.com/ruby/ruby/blob/trunk/parse.y#L11273
 
     args->opt_args       = opt_args;
 
+    args->ruby2_keywords = rest_arg == idFWD_REST;
+
     p->ruby_sourceline = saved_line;
     nd_set_loc(tail, loc);
 
diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb
index cbcdefb..5c2a9fc 100644
--- a/test/ruby/test_syntax.rb
+++ b/test/ruby/test_syntax.rb
@@ -1527,13 +1527,23 @@ eom https://github.com/ruby/ruby/blob/trunk/test/ruby/test_syntax.rb#L1527
     obj3.instance_eval('def foo(...) bar(...) end', __FILE__, __LINE__)
 
     [obj1, obj2, obj3].each do |obj|
-      assert_equal([[1, 2, 3], {k1: 4, k2: 5}], obj.foo(1, 2, 3, k1: 4, k2: 5) {|*x| x})
-      assert_equal([[1, 2, 3], {k1: 4, k2: 5}], obj.foo(1, 2, 3, k1: 4, k2: 5))
+      assert_warning('') {
+        assert_equal([[1, 2, 3], {k1: 4, k2: 5}], obj.foo(1, 2, 3, k1: 4, k2: 5) {|*x| x})
+      }
+      assert_warning('') {
+        assert_equal([[1, 2, 3], {k1: 4, k2: 5}], obj.foo(1, 2, 3, k1: 4, k2: 5))
+      }
+      warning = "warning: The last argument is used as the keyword parameter"
+      assert_warning(/\A\z|:(?!#{__LINE__+1})\d+: #{warning}/o) {
+        assert_equal([[], {}], obj.foo({}) {|*x| x})
+      }
+      assert_warning(/\A\z|:(?!#{__LINE__+1})\d+: #{warning}/o) {
+        assert_equal([[], {}], obj.foo({}))
+      }
       assert_equal(-1, obj.:foo.arity)
       parameters = obj.:foo.parameters
       assert_equal(:rest, parameters.dig(0, 0))
-      assert_equal(:keyrest, parameters.dig(1, 0))
-      assert_equal(:block, parameters.dig(2, 0))
+      assert_equal(:block, parameters.dig(1, 0))
     end
   end
 
-- 
cgit v0.10.2


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

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