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:
parent
48c04ad0d8
commit
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>
|
Wed Jun 27 21:01:32 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* class.c (class_instance_method_list): m_tbl in prepended
|
* 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;
|
return (VALUE)klass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int include_modules_at(VALUE klass, VALUE c, VALUE module);
|
||||||
|
|
||||||
void
|
void
|
||||||
rb_include_module(VALUE klass, VALUE module)
|
rb_include_module(VALUE klass, VALUE module)
|
||||||
{
|
{
|
||||||
VALUE p, c;
|
|
||||||
int changed = 0;
|
int changed = 0;
|
||||||
|
|
||||||
rb_frozen_class_p(klass);
|
rb_frozen_class_p(klass);
|
||||||
@ -666,7 +667,17 @@ rb_include_module(VALUE klass, VALUE module)
|
|||||||
}
|
}
|
||||||
|
|
||||||
OBJ_INFECT(klass, 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) {
|
while (module) {
|
||||||
int superclass_seen = FALSE;
|
int superclass_seen = FALSE;
|
||||||
|
|
||||||
@ -696,13 +707,15 @@ rb_include_module(VALUE klass, VALUE module)
|
|||||||
skip:
|
skip:
|
||||||
module = RCLASS_SUPER(module);
|
module = RCLASS_SUPER(module);
|
||||||
}
|
}
|
||||||
if (changed) rb_clear_cache();
|
|
||||||
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
rb_prepend_module(VALUE klass, VALUE module)
|
rb_prepend_module(VALUE klass, VALUE module)
|
||||||
{
|
{
|
||||||
VALUE p, c, origin;
|
VALUE p, c, origin;
|
||||||
|
int changed = 0;
|
||||||
|
|
||||||
rb_frozen_class_p(klass);
|
rb_frozen_class_p(klass);
|
||||||
if (!OBJ_UNTRUSTED(klass)) {
|
if (!OBJ_UNTRUSTED(klass)) {
|
||||||
@ -714,7 +727,7 @@ rb_prepend_module(VALUE klass, VALUE module)
|
|||||||
OBJ_INFECT(klass, module);
|
OBJ_INFECT(klass, module);
|
||||||
c = RCLASS_SUPER(klass);
|
c = RCLASS_SUPER(klass);
|
||||||
if (RCLASS_M_TBL(klass) == RCLASS_M_TBL(module))
|
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)) {
|
for (p = c; p; p = RCLASS_SUPER(p)) {
|
||||||
if (BUILTIN_TYPE(p) == T_ICLASS) {
|
if (BUILTIN_TYPE(p) == T_ICLASS) {
|
||||||
if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) {
|
if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) {
|
||||||
@ -733,9 +746,12 @@ rb_prepend_module(VALUE klass, VALUE module)
|
|||||||
c = origin;
|
c = origin;
|
||||||
}
|
}
|
||||||
RCLASS_SUPER(klass) = include_class_new(module, c);
|
RCLASS_SUPER(klass) = include_class_new(module, c);
|
||||||
if (RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries) {
|
if (RCLASS_SUPER(module)) {
|
||||||
rb_clear_cache_by_class(klass);
|
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)
|
assert_equal(expected, obj.m1)
|
||||||
end
|
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
|
def test_prepend_instance_methods
|
||||||
bug6655 = '[ruby-core:45915]'
|
bug6655 = '[ruby-core:45915]'
|
||||||
assert_equal(Object.instance_methods, Class.new {prepend Module.new}.instance_methods, bug6655)
|
assert_equal(Object.instance_methods, Class.new {prepend Module.new}.instance_methods, bug6655)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user