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

ruby-changes:37399

From: shugo <ko1@a...>
Date: Tue, 3 Feb 2015 15:27:00 +0900 (JST)
Subject: [ruby-changes:37399] shugo:r49480 (trunk): * vm_method.c (remove_method): When remove refined

shugo	2015-02-03 15:26:48 +0900 (Tue, 03 Feb 2015)

  New Revision: 49480

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

  Log:
    * vm_method.c (remove_method): When remove refined
      method, raise a NameError if the method is not
      defined in refined class.
    
      But if the method is defined in refined class,
      it should keep refined method and remove original
      method.
    
      Patch by Seiei Higa. [ruby-core:67722] [Bug #10765]

  Modified files:
    trunk/ChangeLog
    trunk/test/ruby/test_refinement.rb
    trunk/vm_method.c
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 49479)
+++ ChangeLog	(revision 49480)
@@ -1,3 +1,15 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Tue Feb  3 15:23:58 2015  Shugo Maeda  <shugo@r...>
+
+	* vm_method.c (remove_method): When remove refined
+	  method, raise a NameError if the method is not
+	  defined in refined class.
+	
+	  But if the method is defined in refined class,
+	  it should keep refined method and remove original
+	  method.
+	  
+	  Patch by Seiei Higa. [ruby-core:67722] [Bug #10765]
+
 Tue Feb  3 14:04:47 2015  Nobuyoshi Nakada  <nobu@r...>
 
 	* dir.c (glob_helper): obtain real name with FindFirstFile API
Index: vm_method.c
===================================================================
--- vm_method.c	(revision 49479)
+++ vm_method.c	(revision 49480)
@@ -766,10 +766,12 @@ remove_method(VALUE klass, ID mid) https://github.com/ruby/ruby/blob/trunk/vm_method.c#L766
 
     if (!st_lookup(RCLASS_M_TBL(klass), mid, &data) ||
 	!(me = (rb_method_entry_t *)data) ||
-	(!me->def || me->def->type == VM_METHOD_TYPE_UNDEF)) {
+	(!me->def || me->def->type == VM_METHOD_TYPE_UNDEF) ||
+        UNDEFINED_REFINED_METHOD_P(me->def)) {
 	rb_name_error(mid, "method `%"PRIsVALUE"' not defined in %"PRIsVALUE,
 		      rb_id2str(mid), rb_class_path(klass));
     }
+
     key = (st_data_t)mid;
     st_delete(RCLASS_M_TBL(klass), &key, &data);
 
@@ -777,6 +779,10 @@ remove_method(VALUE klass, ID mid) https://github.com/ruby/ruby/blob/trunk/vm_method.c#L779
     rb_clear_method_cache_by_class(klass);
     rb_unlink_method_entry(me);
 
+    if (me->def->type == VM_METHOD_TYPE_REFINED) {
+	rb_add_refined_method_entry(klass, mid);
+    }
+
     CALL_METHOD_HOOK(self, removed, mid);
 }
 
Index: test/ruby/test_refinement.rb
===================================================================
--- test/ruby/test_refinement.rb	(revision 49479)
+++ test/ruby/test_refinement.rb	(revision 49480)
@@ -1310,6 +1310,58 @@ class TestRefinement < Test::Unit::TestC https://github.com/ruby/ruby/blob/trunk/test/ruby/test_refinement.rb#L1310
     end;
   end
 
+  def test_remove_refined_method
+    assert_separately([], <<-"end;")
+    bug10765 = '[ruby-core:67722] [Bug #10765]'
+
+    class C
+      def foo
+        "C#foo"
+      end
+    end
+
+    module RefinementBug
+      refine C do
+        def foo
+          "RefinementBug#foo"
+        end
+      end
+    end
+
+    using RefinementBug
+
+    class C
+      remove_method :foo
+    end
+
+    assert_equal("RefinementBug#foo", C.new.foo, bug10765)
+    end;
+  end
+
+  def test_remove_undefined_refined_method
+    assert_separately([], <<-"end;")
+    bug10765 = '[ruby-core:67722] [Bug #10765]'
+
+    class C
+    end
+
+    module RefinementBug
+      refine C do
+        def foo
+        end
+      end
+    end
+
+    using RefinementBug
+
+    assert_raise(NameError, bug10765) {
+      class C
+        remove_method :foo
+      end
+    }
+    end;
+  end
+
   private
 
   def eval_using(mod, s)

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

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