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

ruby-changes:24994

From: shugo <ko1@a...>
Date: Fri, 28 Sep 2012 15:48:33 +0900 (JST)
Subject: [ruby-changes:24994] shugo:r37046 (trunk): * vm_method.c (search_method): copy refinement iclasses to search

shugo	2012-09-28 15:48:20 +0900 (Fri, 28 Sep 2012)

  New Revision: 37046

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

  Log:
    * vm_method.c (search_method): copy refinement iclasses to search
      superclasses correctly.
    
    * test/ruby/test_refinement.rb: related test.

  Modified files:
    trunk/ChangeLog
    trunk/test/ruby/test_refinement.rb
    trunk/vm_method.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 37045)
+++ ChangeLog	(revision 37046)
@@ -1,3 +1,10 @@
+Fri Sep 28 15:44:45 2012  Shugo Maeda  <shugo@r...>
+
+	* vm_method.c (search_method): copy refinement iclasses to search
+	  superclasses correctly.
+
+	* test/ruby/test_refinement.rb: related test.
+
 Fri Sep 28 15:15:41 2012  Koichi Sasada  <ko1@a...>
 
 	* insns.def (opt_checkenv): remove unused instruction `opt_checkenv'.
Index: vm_method.c
===================================================================
--- vm_method.c	(revision 37045)
+++ vm_method.c	(revision 37046)
@@ -376,6 +376,24 @@
     return 0;
 }
 
+static VALUE
+copy_refinement_iclass(VALUE iclass, VALUE superclass)
+{
+    VALUE result, c;
+
+    Check_Type(iclass, T_ICLASS);
+    c = result = rb_include_class_new(RBASIC(iclass)->klass, superclass);
+    RCLASS_REFINED_CLASS(c) = RCLASS_REFINED_CLASS(iclass);
+    iclass = RCLASS_SUPER(iclass);
+    while (iclass && BUILTIN_TYPE(iclass) == T_ICLASS) {
+	c = RCLASS_SUPER(c) = rb_include_class_new(RBASIC(iclass)->klass,
+						   RCLASS_SUPER(c));
+	RCLASS_REFINED_CLASS(c) = RCLASS_REFINED_CLASS(iclass);
+	iclass = RCLASS_SUPER(iclass);
+    }
+    return result;
+}
+
 static rb_method_entry_t*
 search_method(VALUE klass, ID id, VALUE omod, VALUE *defined_class_ptr)
 {
@@ -386,15 +404,12 @@
 	st_table *m_tbl;
 
 	if (!NIL_P(omod) && klass != skipped_class) {
-	    VALUE c;
-
-	    if (BUILTIN_TYPE(klass) == T_ICLASS) {
-		c = RBASIC(klass)->klass;
+	    iclass = rb_hash_lookup(omod, klass);
+	    if (NIL_P(iclass) && BUILTIN_TYPE(klass) == T_ICLASS) {
+		iclass = rb_hash_lookup(omod, RBASIC(klass)->klass);
+		if (!NIL_P(iclass))
+		    iclass = copy_refinement_iclass(iclass, klass);
 	    }
-	    else {
-		c = klass;
-	    }
-	    iclass = rb_hash_lookup(omod, c);
 	    if (!NIL_P(iclass)) {
 		skipped_class = klass;
 		klass = iclass;
Index: test/ruby/test_refinement.rb
===================================================================
--- test/ruby/test_refinement.rb	(revision 37045)
+++ test/ruby/test_refinement.rb	(revision 37046)
@@ -361,6 +361,24 @@
     assert_equal([:m1, :m2], m2.module_eval { obj.foo })
   end
 
+  def test_refine_module_and_call_superclass_method
+    m1 = Module.new
+    c1 = Class.new {
+      def foo
+        "c1#foo"
+      end
+    }
+    c2 = Class.new(c1) {
+      include m1
+    }
+    m2 = Module.new {
+      refine m1 do
+      end
+    }
+    obj = c2.new
+    assert_equal("c1#foo", m2.module_eval { obj.foo })
+  end
+
   def test_refine_neither_class_nor_module
     assert_raise(TypeError) do
       Module.new {

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

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