From 2a1ea7d605545c1a5c729cb8b096b296c1c56df4 Mon Sep 17 00:00:00 2001 From: dearblue Date: Sat, 23 Dec 2023 21:01:42 +0900 Subject: [PATCH] Inherit `MRB_FL_UNDEF_ALLOCATE` in subclasses If `Class#allocate` is prohibited, subclasses should also be implicitly prohibited. ```ruby p Class.new(Struct).allocate.class # => # by #6122 # => allocator undefined for # (TypeError) by Ruby 3.2 ``` Added `MRB_DEFINE_ALLOCATOR()` to allow subclasses to use `Class#allocate`. Supplement to #6122. --- include/mruby/class.h | 1 + mrbgems/mruby-data/src/data.c | 1 + mrbgems/mruby-struct/src/struct.c | 1 + src/class.c | 1 + 4 files changed, 4 insertions(+) diff --git a/include/mruby/class.h b/include/mruby/class.h index 1bf71aa6c..5be1b8e91 100644 --- a/include/mruby/class.h +++ b/include/mruby/class.h @@ -78,6 +78,7 @@ mrb_class(mrb_state *mrb, mrb_value v) #define MRB_FL_UNDEF_ALLOCATE (1 << 6) #define MRB_UNDEF_ALLOCATOR(c) (mrb_assert((c)->tt == MRB_TT_CLASS), (c)->flags |= MRB_FL_UNDEF_ALLOCATE) #define MRB_UNDEF_ALLOCATOR_P(c) ((c)->flags & MRB_FL_UNDEF_ALLOCATE) +#define MRB_DEFINE_ALLOCATOR(c) ((c)->flags &= ~MRB_FL_UNDEF_ALLOCATE) MRB_API void mrb_define_method_raw(mrb_state*, struct RClass*, mrb_sym, mrb_method_t); MRB_API void mrb_alias_method(mrb_state*, struct RClass *c, mrb_sym a, mrb_sym b); diff --git a/mrbgems/mruby-data/src/data.c b/mrbgems/mruby-data/src/data.c index 2fbc51242..46f3c0255 100644 --- a/mrbgems/mruby-data/src/data.c +++ b/mrbgems/mruby-data/src/data.c @@ -228,6 +228,7 @@ make_data_class(mrb_state *mrb, mrb_value members, struct RClass *klass) { struct RClass *c = mrb_class_new(mrb, klass); MRB_SET_INSTANCE_TT(c, MRB_TT_STRUCT); + MRB_DEFINE_ALLOCATOR(c); mrb_value data = mrb_obj_value(c); mrb_iv_set(mrb, data, MRB_SYM(__members__), members); diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c index f4a5bab9a..a615607a0 100644 --- a/mrbgems/mruby-struct/src/struct.c +++ b/mrbgems/mruby-struct/src/struct.c @@ -210,6 +210,7 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass *kl c = mrb_define_class_under_id(mrb, klass, id, klass); } MRB_SET_INSTANCE_TT(c, MRB_TT_STRUCT); + MRB_DEFINE_ALLOCATOR(c); nstr = mrb_obj_value(c); mrb_iv_set(mrb, nstr, MRB_SYM(__members__), members); diff --git a/src/class.c b/src/class.c index 4eac5f240..ab39a6fc4 100644 --- a/src/class.c +++ b/src/class.c @@ -2207,6 +2207,7 @@ mrb_class_new(mrb_state *mrb, struct RClass *super) c = boot_defclass(mrb, super); if (super) { MRB_SET_INSTANCE_TT(c, MRB_INSTANCE_TT(super)); + c->flags |= super->flags & MRB_FL_UNDEF_ALLOCATE; } make_metaclass(mrb, c);