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

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36237 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2012-06-27 12:31:17 +00:00
Родитель 48c04ad0d8
Коммит cf3a8f09b8
3 изменённых файлов: 36 добавлений и 6 удалений

Просмотреть файл

@ -1,3 +1,8 @@
Wed Jun 27 21:31:13 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
* 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@ruby-lang.org>
* class.c (class_instance_method_list): m_tbl in prepended

28
class.c
Просмотреть файл

@ -650,10 +650,11 @@ include_class_new(VALUE module, VALUE super)
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 @@ rb_include_module(VALUE klass, VALUE module)
}
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 @@ rb_include_module(VALUE klass, VALUE module)
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 @@ rb_prepend_module(VALUE klass, VALUE module)
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 @@ rb_prepend_module(VALUE klass, VALUE module)
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();
}
/*

Просмотреть файл

@ -1271,6 +1271,15 @@ class TestModule < Test::Unit::TestCase
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)