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

ruby-changes:60416

From: Jeremy <ko1@a...>
Date: Sun, 15 Mar 2020 20:53:07 +0900 (JST)
Subject: [ruby-changes:60416] 3efbd527a8 (ruby_2_7): Do not autosplat when calling proc with empty keyword splat

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

From 3efbd527a86203406664a01126784a10eb136405 Mon Sep 17 00:00:00 2001
From: Jeremy Evans <code@j...>
Date: Fri, 24 Jan 2020 12:13:41 -0800
Subject: Do not autosplat when calling proc with empty keyword splat

With the removal of the splatted argument when using an empty
keyword splat, the autosplat code considered an empty keyword
splat the same as no argument at all.  However, that results
in autosplat behavior changing dependent on the content of
the splatted hash, which is not what anyone would expect or
want.  This change always skips an autosplat if keywords were
provided.

Fixes [Bug #16560]

(cherry picked from commit c1d8829ef515ee51fadeadd7dd022b5c47a71cdd)

diff --git a/test/ruby/test_proc.rb b/test/ruby/test_proc.rb
index c6572ec..3f0d599 100644
--- a/test/ruby/test_proc.rb
+++ b/test/ruby/test_proc.rb
@@ -1087,6 +1087,26 @@ class TestProc < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_proc.rb#L1087
     assert_equal([1,2,[3],4,5], r, "[ruby-core:19485]")
   end
 
+  def test_proc_autosplat
+    def self.a(arg, kw)
+      yield arg
+      yield arg, **kw
+      yield arg, kw
+    end
+
+    arr = []
+    a([1,2,3], {}) do |arg1, arg2=0|
+      arr << [arg1, arg2]
+    end
+    assert_equal([[1, 2], [[1, 2, 3], 0], [[1, 2, 3], {}]], arr)
+
+    arr = []
+    a([1,2,3], a: 1) do |arg1, arg2=0|
+      arr << [arg1, arg2]
+    end
+    assert_equal([[1, 2], [[1, 2, 3], {a: 1}], [[1, 2, 3], {a: 1}]], arr)
+  end
+
   def test_parameters
     assert_equal([], proc {}.parameters)
     assert_equal([], proc {||}.parameters)
diff --git a/vm_args.c b/vm_args.c
index 1efb84a..cf0328d 100644
--- a/vm_args.c
+++ b/vm_args.c
@@ -725,10 +725,10 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co https://github.com/ruby/ruby/blob/trunk/vm_args.c#L725
 {
     const int min_argc = iseq->body->param.lead_num + iseq->body->param.post_num;
     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;
     unsigned int kw_flag = ci->flag & (VM_CALL_KWARG | VM_CALL_KW_SPLAT);
+    int opt_pc = 0, allow_autosplat = !kw_flag;
     struct args_info args_body, *args;
     VALUE keyword_hash = Qnil;
     VALUE * const orig_sp = ec->cfp->sp;
@@ -879,6 +879,7 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co https://github.com/ruby/ruby/blob/trunk/vm_args.c#L879
 	break; /* do nothing special */
       case arg_setup_block:
 	if (given_argc == 1 &&
+            allow_autosplat &&
 	    (min_argc > 0 || iseq->body->param.opt_num > 1 ||
 	     iseq->body->param.flags.has_kw || iseq->body->param.flags.has_kwrest) &&
 	    !iseq->body->param.flags.ambiguous_param0 &&
-- 
cgit v0.10.2


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

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