Issue #5283 has been updated by Koichi Sasada.

Status changed from Open to Assigned
Assignee set to Nobuyoshi Nakada


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

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


 ???????????????
 ???????????????? 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;


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