Issue #5283 has been updated by nobu (Nobuyoshi Nakada).

Description updated


----------------------------------------
Bug #5283:  ???????????????? clone ????????質??
https://bugs.ruby-lang.org/issues/5283#change-34352

Author: shiba (satoshi shiba)
Status: Assigned
Priority: Normal
Assignee: nobu (Nobuyoshi Nakada)
Category: 
Target version: 
ruby -v: -


=begin
???????????????
???????????????? clone ????????????????????????質???????????????????????

+ ???????????
 String.class_eval do
   def self.singleton_method_added(mid)
     puts("singleton_method_added: self = #{self}, mid = #{mid}")
   end
 end
 
 puts("start clone")
 StrClone = String.clone
 puts("finish clone")
 
+ ????????????????????
 singleton_method_added: self = String, mid = singleton_method_added
 start clone
 singleton_method_added: self = String, mid = try_convert
 singleton_method_added: self = String, mid = singleton_method_added
 finish clone



?????????????????????????????String ?????? clone ????????????????????
??????? StrClone ????????????????????????String ?????対??????
singleton_method_added ??????????????????????????????????????????????
質??????????????????????????????? clone ?????? clone ???????????????
??????? singleton_method_added ???????????????????????????????????????

??????????????????????StrClone ??? singleton_method_added ????????
?????????????????????????? singleton_method_added ?????????????????????????????????
singleton_method_added ???使?????????????????

????????????????? String ?????? singleton_method_added ?????????
????????????????rb_singleton_class_clone(class.c) ??????????????
rb_singleton_class_clone ?????以????????????????????????????
????????????????????????????????????"__attached__" ????????????????????
???????????????????



 VALUE
 rb_singleton_class_clone(VALUE obj)
 {
         ...
         if (RCLASS_IV_TBL(klass)) {
             /* ?????????????????? */
             RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(klass));
         }
         ...
         RCLASS_M_TBL(clone) = st_init_numtable();
         data.tbl = RCLASS_M_TBL(clone);
         data.klass = (VALUE)clone;
         /* ?????????????????????????method_added ??????? */
         st_foreach(RCLASS_M_TBL(klass), clone_method,
                    (st_data_t)&data);
         ...
 }



???????????????????????"__attached__" ??????????????????????? String
???????????????????????singleton_method_added ????????? CALL_METHOD_HOOK
?????以?????????????????????????????? "__attached__" ???????決????
?????????????????????????????????????????????????
singleton_method_added ?????????????String ??????????????



 #define CALL_METHOD_HOOK(klass, hook, mid) do {         \
         const VALUE arg = ID2SYM(mid);                  \
         VALUE recv_class = (klass);                     \
         ID hook_id = (hook);                            \
         if (FL_TEST((klass), FL_SINGLETON)) {           \
             recv_class = rb_ivar_get((klass), attached);\
             hook_id = singleton_##hook;                 \
         }                                               \
         rb_funcall2(recv_class, hook_id, 1, &arg);      \
     } while (0)



????????????????????????????????????????????????????????????????????????????
singleton_method_added ??????????????????????????????????????????
?????????????????????????????????????尾??張???????????????
rb_obj_clone ????
RBASIC(clone)->klass = rb_singleton_class_clone_and_attach(obj, clone);
????置????????????????????????????????????????????????????????????????????????????幸
??????????

以???????????????????????????????????????


+ ?????????

 Index: object.c
 ===================================================================
 --- object.c    (revision 33202)
 +++ object.c    (working copy)
 @@ -268,6 +268,7 @@
   *  the class.
   */
 
 +VALUE rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach);
  VALUE
  rb_obj_clone(VALUE obj)
  {
 @@ -277,9 +278,9 @@
          rb_raise(rb_eTypeError, "can't clone %s", rb_obj_classname(obj));
      }
      clone = rb_obj_alloc(rb_obj_class(obj));
 -    RBASIC(clone)->klass = rb_singleton_class_clone(obj);
      RBASIC(clone)->flags = (RBASIC(obj)->flags | FL_TEST(clone, FL_TAINT) | FL_TEST(clone, FL_UNTRUSTED)) & ~(FL_FREEZE|FL_FINALIZE|FL_MARK);
      init_copy(clone, obj);
 +    RBASIC(clone)->klass = rb_singleton_class_clone_and_attach(obj, clone);
      rb_funcall(clone, id_init_clone, 1, obj);
      RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE;
 
 Index: class.c
 ===================================================================
 --- class.c     (revision 33202)
 +++ class.c     (working copy)
 @@ -219,9 +219,17 @@
      return rb_mod_init_copy(clone, orig);
  }
 
 +VALUE rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach);
 +
  VALUE
  rb_singleton_class_clone(VALUE obj)
  {
 +    return rb_singleton_class_clone_and_attach(obj, Qundef);
 +}
 +
 +VALUE
 +rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach)
 +{
      VALUE klass = RBASIC(obj)->klass;
 
      if (!FL_TEST(klass, FL_SINGLETON))
 @@ -246,6 +254,10 @@
             RCLASS_CONST_TBL(clone) = st_init_numtable();
             st_foreach(RCLASS_CONST_TBL(klass), clone_const_i, (st_data_t)RCLASS_CONST_TBL(clone));
         }
 +       if (attach != Qundef) {
 +           rb_singleton_class_attached(clone, attach);
 +       }
         RCLASS_M_TBL(clone) = st_init_numtable();
         data.tbl = RCLASS_M_TBL(clone);
         data.klass = (VALUE)clone;
=end



-- 
http://bugs.ruby-lang.org/