From b929af430c39df6597d2f3f53b82c38b1d76217b Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 24 Sep 2021 01:30:00 +0900 Subject: [PATCH] Use the flag for uninitialized module [Bug #18185] Make `Module#ancestors` not to include `BasicObject`. --- class.c | 15 +++++++++------ test/ruby/test_module.rb | 3 +++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/class.c b/class.c index 8e37f8a93e..ca8bdc2e79 100644 --- a/class.c +++ b/class.c @@ -351,19 +351,22 @@ copy_tables(VALUE clone, VALUE orig) static bool ensure_origin(VALUE klass); +/** + * If this flag is set, that module is allocated but not initialized yet. + */ +enum {RMODULE_ALLOCATED_BUT_NOT_INITIALIZED = RUBY_FL_USER5}; + static inline bool RMODULE_UNINITIALIZED(VALUE module) { - return RCLASS_SUPER(module) == rb_cBasicObject; + return FL_TEST_RAW(module, RMODULE_ALLOCATED_BUT_NOT_INITIALIZED); } void rb_module_set_initialized(VALUE mod) { - if (RMODULE_UNINITIALIZED(mod)) { - RB_OBJ_WRITE(mod, &RCLASS(mod)->super, 0); - /* no more re-initialization */ - } + FL_UNSET_RAW(mod, RMODULE_ALLOCATED_BUT_NOT_INITIALIZED); + /* no more re-initialization */ } void @@ -817,7 +820,7 @@ rb_module_s_alloc(VALUE klass) { VALUE mod = class_alloc(T_MODULE, klass); RCLASS_M_TBL_INIT(mod); - RB_OBJ_WRITE(mod, &RCLASS(mod)->super, rb_cBasicObject); + FL_SET(mod, RMODULE_ALLOCATED_BUT_NOT_INITIALIZED); return mod; } diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb index 429fab897e..be23b84c46 100644 --- a/test/ruby/test_module.rb +++ b/test/ruby/test_module.rb @@ -449,7 +449,9 @@ class TestModule < Test::Unit::TestCase class Bug18185 < Module module InstanceMethods end + attr_reader :ancestor_list def initialize + @ancestor_list = ancestors include InstanceMethods end class Foo @@ -470,6 +472,7 @@ class TestModule < Test::Unit::TestCase assert_equal(1, anc.count(BasicObject), ->{anc.inspect}) b = c.new(key: 1) assert_equal(1, b.key) + assert_not_include(mod.ancestor_list, BasicObject) end def test_dup