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

ruby-changes:30790

From: charliesome <ko1@a...>
Date: Sat, 7 Sep 2013 15:44:39 +0900 (JST)
Subject: [ruby-changes:30790] charliesome:r42869 (trunk): * vm_eval.c (vm_call0): fix prototype, the id parameter should be of

charliesome	2013-09-07 15:44:31 +0900 (Sat, 07 Sep 2013)

  New Revision: 42869

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

  Log:
    * vm_eval.c (vm_call0): fix prototype, the id parameter should be of
      type ID, not VALUE
    
    * vm_insnhelper.c (check_match): the rb_funcall family of functions
      does not care about refinements. We need to use
      rb_method_entry_with_refinements instead to call === with
      refinements. Thanks to Jon Conley for reporting this bug.
      [ruby-core:57051] [Bug #8872]
    
    * test/ruby/test_refinement.rb: add test

  Modified files:
    trunk/ChangeLog
    trunk/test/ruby/test_refinement.rb
    trunk/vm_eval.c
    trunk/vm_insnhelper.c
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 42868)
+++ ChangeLog	(revision 42869)
@@ -1,3 +1,16 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Sat Sep  7 15:36:00 2013  Charlie Somerville  <charliesome@r...>
+
+	* vm_eval.c (vm_call0): fix prototype, the id parameter should be of
+	  type ID, not VALUE
+
+	* vm_insnhelper.c (check_match): the rb_funcall family of functions
+	  does not care about refinements. We need to use
+	  rb_method_entry_with_refinements instead to call === with
+	  refinements. Thanks to Jon Conley for reporting this bug.
+	  [ruby-core:57051] [Bug #8872]
+
+	* test/ruby/test_refinement.rb: add test
+
 Sat Sep  7 13:49:40 2013  Kazuki Tsujimoto  <kazuki@c...>
 
 	* variable.c (classname): the name of class that has
Index: vm_eval.c
===================================================================
--- vm_eval.c	(revision 42868)
+++ vm_eval.c	(revision 42869)
@@ -34,7 +34,7 @@ static VALUE send_internal(int argc, con https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L34
 static VALUE vm_call0_body(rb_thread_t* th, rb_call_info_t *ci, const VALUE *argv);
 
 static VALUE
-vm_call0(rb_thread_t* th, VALUE recv, VALUE id, int argc, const VALUE *argv,
+vm_call0(rb_thread_t* th, VALUE recv, ID id, int argc, const VALUE *argv,
 	 const rb_method_entry_t *me, VALUE defined_class)
 {
     rb_call_info_t ci_entry, *ci = &ci_entry;
Index: vm_insnhelper.c
===================================================================
--- vm_insnhelper.c	(revision 42868)
+++ vm_insnhelper.c	(revision 42869)
@@ -931,18 +931,23 @@ rb_equal_opt(VALUE obj1, VALUE obj2) https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L931
 }
 
 static VALUE
+vm_call0(rb_thread_t*, VALUE, ID, int, const VALUE*, const rb_method_entry_t*, VALUE);
+
+static VALUE
 check_match(VALUE pattern, VALUE target, enum vm_check_match_type type)
 {
     switch (type) {
       case VM_CHECKMATCH_TYPE_WHEN:
 	return pattern;
-      case VM_CHECKMATCH_TYPE_CASE:
-	return rb_funcall2(pattern, idEqq, 1, &target);
-      case VM_CHECKMATCH_TYPE_RESCUE: {
+      case VM_CHECKMATCH_TYPE_RESCUE:
 	if (!rb_obj_is_kind_of(pattern, rb_cModule)) {
 	    rb_raise(rb_eTypeError, "class or module required for rescue clause");
 	}
-	return RTEST(rb_funcall2(pattern, idEqq, 1, &target));
+	/* fall through */
+      case VM_CHECKMATCH_TYPE_CASE: {
+	VALUE defined_class;
+	rb_method_entry_t *me = rb_method_entry_with_refinements(CLASS_OF(pattern), idEqq, &defined_class);
+	return vm_call0(GET_THREAD(), pattern, idEqq, 1, &target, me, defined_class);
       }
       default:
 	rb_bug("check_match: unreachable");
Index: test/ruby/test_refinement.rb
===================================================================
--- test/ruby/test_refinement.rb	(revision 42868)
+++ test/ruby/test_refinement.rb	(revision 42869)
@@ -961,6 +961,27 @@ class TestRefinement < Test::Unit::TestC https://github.com/ruby/ruby/blob/trunk/test/ruby/test_refinement.rb#L961
     INPUT
   end
 
+  def test_case_dispatch_is_aware_of_refinements
+    assert_in_out_err([], <<-RUBY, ["refinement used"], [])
+      module RefineSymbol
+        refine Symbol do
+          def ===(other)
+            true
+          end
+        end
+      end
+
+      using RefineSymbol
+
+      case :a
+      when :b
+        puts "refinement used"
+      else
+        puts "refinement not used"
+      end
+    RUBY
+  end
+
   private
 
   def eval_using(mod, s)

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

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