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

ruby-changes:37412

From: shugo <ko1@a...>
Date: Wed, 4 Feb 2015 16:45:35 +0900 (JST)
Subject: [ruby-changes:37412] shugo:r49493 (trunk): * class.c (method_entry_i, class_instance_method_list,

shugo	2015-02-04 16:45:29 +0900 (Wed, 04 Feb 2015)

  New Revision: 49493

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

  Log:
    * class.c (method_entry_i, class_instance_method_list,
      rb_obj_singleton_methods): should not include methods of
      superclasses if recur is false. [ruby-dev:48854] [Bug #10826]

  Modified files:
    trunk/ChangeLog
    trunk/class.c
    trunk/test/ruby/test_refinement.rb
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 49492)
+++ ChangeLog	(revision 49493)
@@ -1,3 +1,9 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Wed Feb  4 15:34:25 2015  Shugo Maeda  <shugo@r...>
+
+	* class.c (method_entry_i, class_instance_method_list,
+	  rb_obj_singleton_methods): should not include methods of
+	  superclasses if recur is false. [ruby-dev:48854] [Bug #10826]
+
 Wed Feb  4 16:32:40 2015  Matt Hoyle  <matt@d...>
 
 	* ext/bigdecimal/bigdecimal.c (VpSetPTR): fix a typo, 'expoennt'
Index: class.c
===================================================================
--- class.c	(revision 49492)
+++ class.c	(revision 49493)
@@ -1125,25 +1125,32 @@ ins_methods_pub_i(st_data_t name, st_dat https://github.com/ruby/ruby/blob/trunk/class.c#L1125
     return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PUBLIC);
 }
 
+struct method_entry_arg {
+    st_table *list;
+    int recur;
+};
+
 static int
 method_entry_i(st_data_t key, st_data_t value, st_data_t data)
 {
     const rb_method_entry_t *me = (const rb_method_entry_t *)value;
-    st_table *list = (st_table *)data;
+    struct method_entry_arg *arg = (struct method_entry_arg *)data;
     long type;
 
     if (me && me->def->type == VM_METHOD_TYPE_REFINED) {
+	VALUE klass = me->klass;
 	me = rb_resolve_refined_method(Qnil, me, NULL);
 	if (!me) return ST_CONTINUE;
+	if (!arg->recur && me->klass != klass) return ST_CONTINUE;
     }
-    if (!st_lookup(list, key, 0)) {
+    if (!st_lookup(arg->list, key, 0)) {
 	if (UNDEFINED_METHOD_ENTRY_P(me)) {
 	    type = -1; /* none */
 	}
 	else {
 	    type = VISI(me->flag);
 	}
-	st_add_direct(list, key, type);
+	st_add_direct(arg->list, key, type);
     }
     return ST_CONTINUE;
 }
@@ -1153,7 +1160,7 @@ class_instance_method_list(int argc, con https://github.com/ruby/ruby/blob/trunk/class.c#L1160
 {
     VALUE ary;
     int recur, prepended = 0;
-    st_table *list;
+    struct method_entry_arg me_arg;
 
     if (argc == 0) {
 	recur = TRUE;
@@ -1169,16 +1176,17 @@ class_instance_method_list(int argc, con https://github.com/ruby/ruby/blob/trunk/class.c#L1176
 	prepended = 1;
     }
 
-    list = st_init_numtable();
+    me_arg.list = st_init_numtable();
+    me_arg.recur = recur;
     for (; mod; mod = RCLASS_SUPER(mod)) {
-	if (RCLASS_M_TBL(mod)) st_foreach(RCLASS_M_TBL(mod), method_entry_i, (st_data_t)list);
+	if (RCLASS_M_TBL(mod)) st_foreach(RCLASS_M_TBL(mod), method_entry_i, (st_data_t)&me_arg);
 	if (BUILTIN_TYPE(mod) == T_ICLASS && !prepended) continue;
 	if (obj && FL_TEST(mod, FL_SINGLETON)) continue;
 	if (!recur) break;
     }
     ary = rb_ary_new();
-    st_foreach(list, func, ary);
-    st_free_table(list);
+    st_foreach(me_arg.list, func, ary);
+    st_free_table(me_arg.list);
 
     return ary;
 }
@@ -1391,7 +1399,8 @@ VALUE https://github.com/ruby/ruby/blob/trunk/class.c#L1399
 rb_obj_singleton_methods(int argc, const VALUE *argv, VALUE obj)
 {
     VALUE recur, ary, klass, origin;
-    st_table *list, *mtbl;
+    struct method_entry_arg me_arg;
+    st_table *mtbl;
 
     if (argc == 0) {
 	recur = Qtrue;
@@ -1401,22 +1410,23 @@ rb_obj_singleton_methods(int argc, const https://github.com/ruby/ruby/blob/trunk/class.c#L1410
     }
     klass = CLASS_OF(obj);
     origin = RCLASS_ORIGIN(klass);
-    list = st_init_numtable();
+    me_arg.list = st_init_numtable();
+    me_arg.recur = recur;
     if (klass && FL_TEST(klass, FL_SINGLETON)) {
 	if ((mtbl = RCLASS_M_TBL(origin)) != 0)
-	    st_foreach(mtbl, method_entry_i, (st_data_t)list);
+	    st_foreach(mtbl, method_entry_i, (st_data_t)&me_arg);
 	klass = RCLASS_SUPER(klass);
     }
     if (RTEST(recur)) {
 	while (klass && (FL_TEST(klass, FL_SINGLETON) || RB_TYPE_P(klass, T_ICLASS))) {
 	    if (klass != origin && (mtbl = RCLASS_M_TBL(klass)) != 0)
-		st_foreach(mtbl, method_entry_i, (st_data_t)list);
+		st_foreach(mtbl, method_entry_i, (st_data_t)&me_arg);
 	    klass = RCLASS_SUPER(klass);
 	}
     }
     ary = rb_ary_new();
-    st_foreach(list, ins_methods_i, ary);
-    st_free_table(list);
+    st_foreach(me_arg.list, ins_methods_i, ary);
+    st_free_table(me_arg.list);
 
     return ary;
 }
Index: test/ruby/test_refinement.rb
===================================================================
--- test/ruby/test_refinement.rb	(revision 49492)
+++ test/ruby/test_refinement.rb	(revision 49493)
@@ -1362,6 +1362,31 @@ class TestRefinement < Test::Unit::TestC https://github.com/ruby/ruby/blob/trunk/test/ruby/test_refinement.rb#L1362
     end;
   end
 
+  module NotIncludeSuperclassMethod
+    class X
+      def foo
+      end
+    end
+
+    class Y < X
+    end
+
+    module Bar
+      refine Y do
+        def foo
+        end
+      end
+    end
+  end
+
+  def test_instance_methods_not_include_superclass_method
+    bug10826 = '[ruby-dev:48854] [Bug #10826]'
+    assert_not_include(NotIncludeSuperclassMethod::Y.instance_methods(false),
+                       :foo, bug10826)
+    assert_include(NotIncludeSuperclassMethod::Y.instance_methods(true),
+                   :foo, bug10826)
+  end
+
   private
 
   def eval_using(mod, s)

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

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