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

ruby-changes:50737

From: nobu <ko1@a...>
Date: Sun, 25 Mar 2018 11:22:19 +0900 (JST)
Subject: [ruby-changes:50737] nobu:r62914 (trunk): vm_args.c: warn splat to var

nobu	2018-03-25 11:22:14 +0900 (Sun, 25 Mar 2018)

  New Revision: 62914

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=62914

  Log:
    vm_args.c: warn splat to var
    
    * vm_args.c (setup_parameters_complex): [EXPERIMENTAL] warn when
      splat keyword arguments is passed as a single ordinary argument,
      not as a keyword rest argument.

  Modified files:
    trunk/test/ruby/test_keyword.rb
    trunk/vm_args.c
Index: vm_args.c
===================================================================
--- vm_args.c	(revision 62913)
+++ vm_args.c	(revision 62914)
@@ -509,6 +509,7 @@ setup_parameters_complex(rb_execution_co https://github.com/ruby/ruby/blob/trunk/vm_args.c#L509
     const int max_argc = (iseq->body->param.flags.has_rest == FALSE) ? min_argc + iseq->body->param.opt_num : UNLIMITED_ARGUMENTS;
     int opt_pc = 0;
     int given_argc;
+    int kw_splat = FALSE;
     struct args_info args_body, *args;
     VALUE keyword_hash = Qnil;
     VALUE * const orig_sp = ec->cfp->sp;
@@ -600,10 +601,12 @@ setup_parameters_complex(rb_execution_co https://github.com/ruby/ruby/blob/trunk/vm_args.c#L601
 	}
     }
 
+    if (ci->flag & VM_CALL_KW_SPLAT) {
+	kw_splat = !iseq->body->param.flags.has_rest;
+    }
     if (given_argc > min_argc &&
 	(iseq->body->param.flags.has_kw || iseq->body->param.flags.has_kwrest ||
-	 (!iseq->body->param.flags.has_rest && given_argc > max_argc &&
-	  (ci->flag & VM_CALL_KW_SPLAT))) &&
+	 (kw_splat && given_argc > max_argc)) &&
 	args->kw_argv == NULL) {
 	if (args_pop_keyword_hash(args, &keyword_hash)) {
 	    given_argc--;
@@ -667,6 +670,10 @@ setup_parameters_complex(rb_execution_co https://github.com/ruby/ruby/blob/trunk/vm_args.c#L670
     else if (!NIL_P(keyword_hash) && RHASH_SIZE(keyword_hash) > 0) {
 	argument_kw_error(ec, iseq, "unknown", rb_hash_keys(keyword_hash));
     }
+    else if (kw_splat && NIL_P(keyword_hash)) {
+	rb_warning("passing splat keyword arguments as a single Hash"
+		   " to `% "PRIsVALUE"'", rb_id2str(ci->mid));
+    }
 
     if (iseq->body->param.flags.has_block) {
 	if (iseq->body->local_iseq == iseq) {
Index: test/ruby/test_keyword.rb
===================================================================
--- test/ruby/test_keyword.rb	(revision 62913)
+++ test/ruby/test_keyword.rb	(revision 62914)
@@ -507,6 +507,7 @@ class TestKeywordArguments < Test::Unit: https://github.com/ruby/ruby/blob/trunk/test/ruby/test_keyword.rb#L507
     m = Object.new
     def m.f() :ok; end
     def m.f2(a = nil) a; end
+    def m.f3(**a) a; end
     o = {a: 1}
     assert_raise_with_message(ArgumentError, /unknown keyword: a/) {
       m.f(**o)
@@ -517,9 +518,16 @@ class TestKeywordArguments < Test::Unit: https://github.com/ruby/ruby/blob/trunk/test/ruby/test_keyword.rb#L518
     assert_equal(:ok, m.f(*a, **o), '[ruby-core:83638] [Bug #10856]')
 
     o = {a: 42}
-    assert_equal({a: 42}, m.f2(**o), '[ruby-core:82280] [Bug #13791]')
+    assert_warning(/splat keyword/) do
+      assert_equal({a: 42}, m.f2(**o), '[ruby-core:82280] [Bug #13791]')
+    end
+    assert_warning('') do
+      assert_equal({a: 42}, m.f3(**o), 'splat to kwrest')
+    end
 
-    assert_equal({a: 42}, m.f2("a".to_sym => 42), '[ruby-core:82291] [Bug #13793]')
+    assert_warning('') do
+      assert_equal({a: 42}, m.f2("a".to_sym => 42), '[ruby-core:82291] [Bug #13793]')
+    end
 
     o = {}
     a = [:ok]

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

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