merge revision(s) 6118e8a473, dc64448202: [Backport #20716]

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]

	Remove an unused variable
This commit is contained in:
nagachika 2024-10-18 13:10:46 +09:00
parent 087e4ed6cc
commit cb75fcef6f
3 changed files with 34 additions and 9 deletions

View file

@ -1213,7 +1213,7 @@ static int
do_include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super, bool check_cyclic) do_include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super, bool check_cyclic)
{ {
VALUE p, iclass, origin_stack = 0; VALUE p, iclass, origin_stack = 0;
int method_changed = 0, add_subclass; int method_changed = 0;
long origin_len; long origin_len;
VALUE klass_origin = RCLASS_ORIGIN(klass); VALUE klass_origin = RCLASS_ORIGIN(klass);
VALUE original_klass = klass; VALUE original_klass = klass;
@ -1277,7 +1277,6 @@ do_include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super
iclass = rb_include_class_new(module, super_class); iclass = rb_include_class_new(module, super_class);
c = RCLASS_SET_SUPER(c, iclass); c = RCLASS_SET_SUPER(c, iclass);
RCLASS_SET_INCLUDER(iclass, klass); RCLASS_SET_INCLUDER(iclass, klass);
add_subclass = TRUE;
if (module != RCLASS_ORIGIN(module)) { if (module != RCLASS_ORIGIN(module)) {
if (!origin_stack) origin_stack = rb_ary_hidden_new(2); if (!origin_stack) origin_stack = rb_ary_hidden_new(2);
VALUE origin[2] = {iclass, RCLASS_ORIGIN(module)}; VALUE origin[2] = {iclass, RCLASS_ORIGIN(module)};
@ -1288,14 +1287,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); RCLASS_SET_ORIGIN(RARRAY_AREF(origin_stack, (origin_len -= 2)), iclass);
RICLASS_SET_ORIGIN_SHARED_MTBL(iclass); RICLASS_SET_ORIGIN_SHARED_MTBL(iclass);
rb_ary_resize(origin_stack, origin_len); rb_ary_resize(origin_stack, origin_len);
add_subclass = FALSE;
} }
if (add_subclass) {
VALUE m = module; VALUE m = module;
if (BUILTIN_TYPE(m) == T_ICLASS) m = METACLASS_OF(m); if (BUILTIN_TYPE(m) == T_ICLASS) m = METACLASS_OF(m);
rb_module_add_to_subclasses_list(m, iclass); rb_module_add_to_subclasses_list(m, iclass);
}
if (BUILTIN_TYPE(klass) == T_MODULE && FL_TEST(klass, RMODULE_IS_REFINEMENT)) { if (BUILTIN_TYPE(klass) == T_MODULE && FL_TEST(klass, RMODULE_IS_REFINEMENT)) {
VALUE refined_class = VALUE refined_class =

View file

@ -605,6 +605,35 @@ class TestSuper < Test::Unit::TestCase
} }
end 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 class TestFor_super_with_modified_rest_parameter_base
def foo *args def foo *args
args args

View file

@ -11,7 +11,7 @@
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
#define RUBY_VERSION_TEENY 5 #define RUBY_VERSION_TEENY 5
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
#define RUBY_PATCHLEVEL 228 #define RUBY_PATCHLEVEL 229
#include "ruby/version.h" #include "ruby/version.h"
#include "ruby/internal/abi.h" #include "ruby/internal/abi.h"