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

ruby-changes:24186

From: nobu <ko1@a...>
Date: Wed, 27 Jun 2012 21:32:25 +0900 (JST)
Subject: [ruby-changes:24186] nobu:r36237 (trunk): ancestor modules

nobu	2012-06-27 21:31:17 +0900 (Wed, 27 Jun 2012)

  New Revision: 36237

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

  Log:
    ancestor modules
    
    * class.c (rb_prepend_module): ancestors of prepending module also
      should be included.  [ruby-core:45914][Bug #6654]

  Modified files:
    trunk/ChangeLog
    trunk/class.c
    trunk/test/ruby/test_module.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 36236)
+++ ChangeLog	(revision 36237)
@@ -1,3 +1,8 @@
+Wed Jun 27 21:31:13 2012  Nobuyoshi Nakada  <nobu@r...>
+
+	* class.c (rb_prepend_module): ancestors of prepending module also
+	  should be included.  [ruby-core:45914][Bug #6654]
+
 Wed Jun 27 21:01:32 2012  Nobuyoshi Nakada  <nobu@r...>
 
 	* class.c (class_instance_method_list): m_tbl in prepended
Index: class.c
===================================================================
--- class.c	(revision 36236)
+++ class.c	(revision 36237)
@@ -650,10 +650,11 @@
     return (VALUE)klass;
 }
 
+static int include_modules_at(VALUE klass, VALUE c, VALUE module);
+
 void
 rb_include_module(VALUE klass, VALUE module)
 {
-    VALUE p, c;
     int changed = 0;
 
     rb_frozen_class_p(klass);
@@ -666,7 +667,17 @@
     }
 
     OBJ_INFECT(klass, module);
-    c = klass;
+
+    changed = include_modules_at(klass, klass, module);
+    if (changed) rb_clear_cache();
+}
+
+static int
+include_modules_at(VALUE klass, VALUE c, VALUE module)
+{
+    VALUE p;
+    int changed = 0;
+
     while (module) {
 	int superclass_seen = FALSE;
 
@@ -696,13 +707,15 @@
       skip:
 	module = RCLASS_SUPER(module);
     }
-    if (changed) rb_clear_cache();
+
+    return changed;
 }
 
 void
 rb_prepend_module(VALUE klass, VALUE module)
 {
     VALUE p, c, origin;
+    int changed = 0;
 
     rb_frozen_class_p(klass);
     if (!OBJ_UNTRUSTED(klass)) {
@@ -714,7 +727,7 @@
     OBJ_INFECT(klass, module);
     c = RCLASS_SUPER(klass);
     if (RCLASS_M_TBL(klass) == RCLASS_M_TBL(module))
-	rb_raise(rb_eArgError, "cyclic include detected");
+	rb_raise(rb_eArgError, "cyclic prepend detected");
     for (p = c; p; p = RCLASS_SUPER(p)) {
 	if (BUILTIN_TYPE(p) == T_ICLASS) {
 	    if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) {
@@ -733,9 +746,12 @@
 	c = origin;
     }
     RCLASS_SUPER(klass) = include_class_new(module, c);
-    if (RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries) {
-	rb_clear_cache_by_class(klass);
+    if (RCLASS_SUPER(module)) {
+	changed = include_modules_at(klass, RCLASS_SUPER(klass), RCLASS_SUPER(module));
     }
+    if (!changed)
+	changed = RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries;
+    if (changed) rb_clear_cache();
 }
 
 /*
Index: test/ruby/test_module.rb
===================================================================
--- test/ruby/test_module.rb	(revision 36236)
+++ test/ruby/test_module.rb	(revision 36237)
@@ -1271,6 +1271,15 @@
     assert_equal(expected, obj.m1)
   end
 
+  def test_prepend_inheritance
+    bug6654 = '[ruby-core:45914]'
+    a = Module.new
+    b = Module.new {include a}
+    c = Class.new {prepend b}
+    assert_operator(c, :<, b, bug6654)
+    assert_operator(c, :<, a, bug6654)
+  end
+
   def test_prepend_instance_methods
     bug6655 = '[ruby-core:45915]'
     assert_equal(Object.instance_methods, Class.new {prepend Module.new}.instance_methods, bug6655)

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

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