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

ruby-changes:58427

From: Jeremy <ko1@a...>
Date: Fri, 25 Oct 2019 04:35:18 +0900 (JST)
Subject: [ruby-changes:58427] d6a2507e49 (master): Duplicate hash when converting keyword hash to keywords

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

From d6a2507e494f0fffca375c9e2eede38b6a777874 Mon Sep 17 00:00:00 2001
From: Jeremy Evans <code@j...>
Date: Thu, 24 Oct 2019 09:47:30 -0700
Subject: Duplicate hash when converting keyword hash to keywords

This mirrors the behavior when manually splatting a hash.  This
mirrors the changes made in setup_parameters_complex in
6081ddd6e6f2297862b3c7e898d28a76b8f9240b, so that splatting to a
non-iseq method works the same as splatting to an iseq method.

diff --git a/test/ruby/test_keyword.rb b/test/ruby/test_keyword.rb
index 2533771..0f67c28 100644
--- a/test/ruby/test_keyword.rb
+++ b/test/ruby/test_keyword.rb
@@ -2692,6 +2692,10 @@ class TestKeywordArguments < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_keyword.rb#L2692
         args
       end
 
+      def pass_cfunc(*args)
+        self.class.new(*args).init_args
+      end
+
       ruby2_keywords def block(*args)
         ->(*args, **kw){[args, kw]}.(*args)
       end
@@ -2915,6 +2919,10 @@ class TestKeywordArguments < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_keyword.rb#L2919
       assert_equal([[1], h1], o.foo(:pass_bar, 1, :a=>1))
     end
 
+    assert_warn(/The last argument is used as the keyword parameter.* for `initialize'/m) do
+      assert_equal([[1], h1], o.foo(:pass_cfunc, 1, :a=>1))
+    end
+
     assert_warn(/Skipping set of ruby2_keywords flag for bar \(method accepts keywords or method does not accept argument splat\)/) do
       assert_nil(c.send(:ruby2_keywords, :bar))
     end
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 44a44d5..c72ad6e 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1783,14 +1783,16 @@ CALLER_SETUP_ARG(struct rb_control_frame_struct *restrict cfp, https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L1783
                  const struct rb_call_info *restrict ci)
 {
     if (UNLIKELY(IS_ARGS_SPLAT(ci))) {
+        VALUE final_hash;
         /* This expands the rest argument to the stack.
          * So, ci->flag & VM_CALL_ARGS_SPLAT is now inconsistent.
          */
         vm_caller_setup_arg_splat(cfp, calling);
         if (!IS_ARGS_KW_OR_KW_SPLAT(ci) &&
                 calling->argc > 0 &&
-                RB_TYPE_P(*(cfp->sp - 1), T_HASH) &&
-                (((struct RHash *)*(cfp->sp - 1))->basic.flags & RHASH_PASS_AS_KEYWORDS)) {
+                RB_TYPE_P((final_hash = *(cfp->sp - 1)), T_HASH) &&
+                (((struct RHash *)final_hash)->basic.flags & RHASH_PASS_AS_KEYWORDS)) {
+            *(cfp->sp - 1) = rb_hash_dup(final_hash);
             calling->kw_splat = 1;
         }
     }
-- 
cgit v0.10.2


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

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