зеркало из https://github.com/github/ruby.git
ancestor modules
* 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:
Родитель
48c04ad0d8
Коммит
cf3a8f09b8
|
@ -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
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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче