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

ruby-changes:34692

From: nobu <ko1@a...>
Date: Thu, 10 Jul 2014 15:03:00 +0900 (JST)
Subject: [ruby-changes:34692] nobu:r46775 (trunk): vm_insnhelper.c: fix implicit splat keyword argument

nobu	2014-07-10 15:02:54 +0900 (Thu, 10 Jul 2014)

  New Revision: 46775

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

  Log:
    vm_insnhelper.c: fix implicit splat keyword argument
    
    * vm_insnhelper.c (vm_callee_setup_keyword_arg): adjust VM stack
      pointer to get rid of overwriting splat arguments by arguments
      for `to_hash` conversion.  [ruby-core:63593] [Bug #10016]

  Modified files:
    trunk/ChangeLog
    trunk/test/ruby/test_keyword.rb
    trunk/vm_insnhelper.c
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 46774)
+++ ChangeLog	(revision 46775)
@@ -1,3 +1,9 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Thu Jul 10 15:02:55 2014  Nobuyoshi Nakada  <nobu@r...>
+
+	* vm_insnhelper.c (vm_callee_setup_keyword_arg): adjust VM stack
+	  pointer to get rid of overwriting splat arguments by arguments
+	  for `to_hash` conversion.  [ruby-core:63593] [Bug #10016]
+
 Thu Jul 10 01:09:57 2014  Koichi Sasada  <ko1@a...>
 
 	* symbol.c: remove rb_gc_mark_symbols().
Index: vm_insnhelper.c
===================================================================
--- vm_insnhelper.c	(revision 46774)
+++ vm_insnhelper.c	(revision 46775)
@@ -1075,10 +1075,15 @@ vm_caller_setup_args(const rb_thread_t * https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L1075
 }
 
 static inline int
-vm_callee_setup_keyword_arg(const rb_iseq_t *iseq, int argc, int m, VALUE *orig_argv, VALUE *kwd)
+vm_callee_setup_keyword_arg(rb_thread_t *th, const rb_iseq_t *iseq, int argc, int m, VALUE *orig_argv, VALUE *kwd)
 {
     VALUE keyword_hash = 0, orig_hash;
     int optional = iseq->arg_keywords - iseq->arg_keyword_required;
+    VALUE *const sp = th->cfp->sp;
+    const int mark_stack_len = th->mark_stack_len;
+
+    th->cfp->sp += argc;
+    th->mark_stack_len -= argc;
 
     if (argc > m &&
 	!NIL_P(orig_hash = rb_check_hash_type(orig_argv[argc-1])) &&
@@ -1093,10 +1098,14 @@ vm_callee_setup_keyword_arg(const rb_ise https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L1098
     rb_get_kwargs(keyword_hash, iseq->arg_keyword_table, iseq->arg_keyword_required,
 		  (iseq->arg_keyword_check ? optional : -1-optional),
 		  NULL);
+
     if (!keyword_hash) {
 	keyword_hash = rb_hash_new();
     }
 
+    th->cfp->sp = sp;
+    th->mark_stack_len = mark_stack_len;
+
     *kwd = keyword_hash;
 
     return argc;
@@ -1120,7 +1129,7 @@ vm_callee_setup_arg_complex(rb_thread_t https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L1129
 
     /* keyword argument */
     if (iseq->arg_keyword != -1) {
-	argc = vm_callee_setup_keyword_arg(iseq, argc, min, orig_argv, &keyword_hash);
+	argc = vm_callee_setup_keyword_arg(th, iseq, argc, min, orig_argv, &keyword_hash);
     }
 
     /* mandatory */
@@ -2242,7 +2251,7 @@ vm_yield_setup_block_args(rb_thread_t *t https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L2251
 
     /* keyword argument */
     if (iseq->arg_keyword != -1) {
-	argc = vm_callee_setup_keyword_arg(iseq, argc, min, argv, &keyword_hash);
+	argc = vm_callee_setup_keyword_arg(th, iseq, argc, min, argv, &keyword_hash);
     }
 
     for (i=argc; i<m; i++) {
Index: test/ruby/test_keyword.rb
===================================================================
--- test/ruby/test_keyword.rb	(revision 46774)
+++ test/ruby/test_keyword.rb	(revision 46775)
@@ -463,6 +463,16 @@ class TestKeywordArguments < Test::Unit: https://github.com/ruby/ruby/blob/trunk/test/ruby/test_keyword.rb#L463
     assert_equal({a: 1, b: 2}, m1(**o, **o2) {|x| break x}, bug9898)
   end
 
+  def test_implicit_hash_conversion
+    bug10016 = '[ruby-core:63593] [Bug #10016]'
+
+    o = Object.new
+    def o.to_hash() { k: 9 } end
+    assert_equal([1, 42, [], o, :key, {}, nil], f9(1, o))
+    assert_equal([1, 9], m1(1, o) {|a, k: 0| break [a, k]}, bug10016)
+    assert_equal([1, 9], m1(1, o, &->(a, k: 0) {break [a, k]}), bug10016)
+  end
+
   def test_gced_object_in_stack
     bug8964 = '[ruby-dev:47729] [Bug #8964]'
     assert_normal_exit %q{

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

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