summaryrefslogtreecommitdiff
path: root/class.c
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2020-07-26 11:52:19 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2021-09-17 11:14:04 +0900
commit178ee1e801acb33d13b3e8a630f6ca4926c68fbc (patch)
treefbc3b2dd31c4a3007580959b79ad08c4dbf36029 /class.c
parent8f41c791b19a47e2dfa39b0a6d12ef964098536a (diff)
downloadruby-178ee1e801acb33d13b3e8a630f6ca4926c68fbc.tar.gz
Already initialized modules cannot be replaced [Bug #17048]
Diffstat (limited to 'class.c')
-rw-r--r--class.c43
1 files changed, 42 insertions, 1 deletions
diff --git a/class.c b/class.c
index d2dd43815c..0b075a9abb 100644
--- a/class.c
+++ b/class.c
@@ -248,6 +248,12 @@ rb_class_new(VALUE super)
return rb_class_boot(super);
}
+VALUE
+rb_class_s_alloc(VALUE klass)
+{
+ return rb_class_boot(0);
+}
+
static void
clone_method(VALUE old_klass, VALUE new_klass, ID mid, const rb_method_entry_t *me)
{
@@ -345,12 +351,35 @@ copy_tables(VALUE clone, VALUE orig)
static bool ensure_origin(VALUE klass);
+static inline bool
+RMODULE_UNINITIALIZED(VALUE module)
+{
+ return RCLASS_SUPER(module) == rb_cBasicObject;
+}
+
+void
+rb_module_check_initialiable(VALUE mod)
+{
+ if (!RMODULE_UNINITIALIZED(mod)) {
+ rb_raise(rb_eTypeError, "already initialized module");
+ }
+ RB_OBJ_WRITE(mod, &RCLASS(mod)->super, 0);
+}
+
/* :nodoc: */
VALUE
rb_mod_init_copy(VALUE clone, VALUE orig)
{
- if (RB_TYPE_P(clone, T_CLASS)) {
+ switch (BUILTIN_TYPE(clone)) {
+ case T_CLASS:
+ case T_ICLASS:
class_init_copy_check(clone, orig);
+ break;
+ case T_MODULE:
+ rb_module_check_initialiable(clone);
+ break;
+ default:
+ break;
}
if (!OBJ_INIT_COPY(clone, orig)) return clone;
@@ -775,6 +804,15 @@ rb_define_class_id_under(VALUE outer, ID id, VALUE super)
}
VALUE
+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);
+ return mod;
+}
+
+VALUE
rb_module_new(void)
{
VALUE mdl = class_alloc(T_MODULE, rb_cModule);
@@ -878,6 +916,9 @@ ensure_includable(VALUE klass, VALUE module)
{
rb_class_modify_check(klass);
Check_Type(module, T_MODULE);
+ if (RMODULE_UNINITIALIZED(module)) {
+ rb_raise(rb_eArgError, "uninitialized module");
+ }
if (!NIL_P(rb_refinement_module_get_refined_class(module))) {
rb_raise(rb_eArgError, "refinement module is not allowed");
}