Fix method caching bug when including/prepend module A that prepends module B
Fix by always adding the generated iclass to the subclasses list, otherwise the method cache for the iclass is not cleared when the method in the module is overwritten. Fixes [Bug #20716]
This commit is contained in:
parent
167fba52f0
commit
6118e8a473
Notes:
git
2024-09-19 14:34:20 +00:00
10
class.c
10
class.c
@ -1336,7 +1336,6 @@ do_include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super
|
||||
iclass = rb_include_class_new(module, super_class);
|
||||
c = RCLASS_SET_SUPER(c, iclass);
|
||||
RCLASS_SET_INCLUDER(iclass, klass);
|
||||
add_subclass = TRUE;
|
||||
if (module != RCLASS_ORIGIN(module)) {
|
||||
if (!origin_stack) origin_stack = rb_ary_hidden_new(2);
|
||||
VALUE origin[2] = {iclass, RCLASS_ORIGIN(module)};
|
||||
@ -1347,14 +1346,11 @@ do_include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super
|
||||
RCLASS_SET_ORIGIN(RARRAY_AREF(origin_stack, (origin_len -= 2)), iclass);
|
||||
RICLASS_SET_ORIGIN_SHARED_MTBL(iclass);
|
||||
rb_ary_resize(origin_stack, origin_len);
|
||||
add_subclass = FALSE;
|
||||
}
|
||||
|
||||
if (add_subclass) {
|
||||
VALUE m = module;
|
||||
if (BUILTIN_TYPE(m) == T_ICLASS) m = METACLASS_OF(m);
|
||||
rb_module_add_to_subclasses_list(m, iclass);
|
||||
}
|
||||
VALUE m = module;
|
||||
if (BUILTIN_TYPE(m) == T_ICLASS) m = METACLASS_OF(m);
|
||||
rb_module_add_to_subclasses_list(m, iclass);
|
||||
|
||||
if (BUILTIN_TYPE(klass) == T_MODULE && FL_TEST(klass, RMODULE_IS_REFINEMENT)) {
|
||||
VALUE refined_class =
|
||||
|
@ -633,6 +633,35 @@ class TestSuper < Test::Unit::TestCase
|
||||
}
|
||||
end
|
||||
|
||||
def test_super_with_included_prepended_module_method_caching_bug_20716
|
||||
a = Module.new do
|
||||
def test(*args)
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
b = Module.new do
|
||||
def test(a)
|
||||
a
|
||||
end
|
||||
end
|
||||
|
||||
c = Class.new
|
||||
|
||||
b.prepend(a)
|
||||
c.include(b)
|
||||
|
||||
assert_equal(1, c.new.test(1))
|
||||
|
||||
b.class_eval do
|
||||
def test
|
||||
:test
|
||||
end
|
||||
end
|
||||
|
||||
assert_equal(:test, c.new.test)
|
||||
end
|
||||
|
||||
class TestFor_super_with_modified_rest_parameter_base
|
||||
def foo *args
|
||||
args
|
||||
|
Loading…
x
Reference in New Issue
Block a user