Use the flag for uninitialized module [Bug #18185]

Make `Module#ancestors` not to include `BasicObject`.
This commit is contained in:
Nobuyoshi Nakada 2021-09-24 01:30:00 +09:00
Родитель 65285bf673
Коммит b929af430c
2 изменённых файлов: 12 добавлений и 6 удалений

15
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;
}

Просмотреть файл

@ -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