なかだです。

At Wed, 24 Dec 2003 17:35:09 +0900,
Yukihiro Matsumoto wrote in [ruby-dev:22379]:
> |> |そういえば、次の `to_s': method `to_s' overridden (TypeError) というの
> |> |はなぜ起こるんでしょうか?
> |> 
> |> なぜか明示的にチェックしてますね。なんでチェックを入れたのか
> |> 全然思い出せないんですけど。3年前の自分は別人だ。
> |
> |どうせチェックするなら、define_methodの時点でしたほうがいいんじゃ
> |ないでしょうか。
> 
> その意見には賛成です。でも、このパッチの挙動にいまいち自信が
> 持てないので(元は自分が書いたコードなのに)、1.8.1には入れま
> せん。

これはどうしましょうか。define_methodの時点でチェックするなら、
NODE_DMETHOD自体不要になるような気がするのですが。

逆にチェック無しのままにするなら、それはそれで #if 0 の部分は削っ
たほうがいいのでは。


Index: eval.c =================================================================== RCS file: /cvs/ruby/src/ruby/eval.c,v retrieving revision 1.634 diff -u -2 -p -d -r1.634 eval.c --- eval.c 22 Jan 2004 08:31:32 -0000 1.634 +++ eval.c 10 Feb 2004 02:24:23 -0000 @@ -5438,8 +5438,4 @@ rb_call0(klass, recv, id, oid, argc, arg break; - case NODE_DMETHOD: - result = method_call(argc, argv, umethod_bind(body->nd_cval, recv)); - break; - case NODE_BMETHOD: result = proc_invoke(body->nd_cval, rb_ary_new4(argc, argv), recv, klass); @@ -8713,10 +8709,8 @@ umethod_bind(method, recv) rb_raise(rb_eTypeError, "singleton method called for a different object"); } -#if 0 if (FL_TEST(CLASS_OF(recv), FL_SINGLETON) && st_lookup(RCLASS(CLASS_OF(recv))->m_tbl, data->oid, 0)) { rb_raise(rb_eTypeError, "method `%s' overridden", rb_id2name(data->oid)); } -#endif if(!rb_obj_is_kind_of(recv, data->rklass)) { rb_raise(rb_eTypeError, "bind argument must be an instance of %s", @@ -8788,5 +8782,4 @@ method_arity(method) return INT2FIX(0); case NODE_BMETHOD: - case NODE_DMETHOD: return proc_arity(body->nd_cval); default: @@ -8914,6 +8907,9 @@ method_proc(method) struct BLOCK *bdata; - proc = rb_iterate((VALUE(*)_((VALUE)))mproc, 0, bmcall, method); Data_Get_Struct(method, struct METHOD, mdata); + if (nd_type(mdata->body) == NODE_BMETHOD) { + return mdata->body->nd_cval; + } + proc = rb_iterate((VALUE(*)_((VALUE)))mproc, 0, bmcall, method); Data_Get_Struct(proc, struct BLOCK, bdata); bdata->body->nd_file = mdata->body->nd_file; @@ -8998,5 +8994,20 @@ rb_mod_define_method(argc, argv, mod) } if (RDATA(body)->dmark == (RUBY_DATA_FUNC)bm_mark) { - node = NEW_DMETHOD(method_unbind(body)); + struct METHOD *method = (struct METHOD *)DATA_PTR(body); + VALUE rklass = method->rklass; + if (rklass != mod) { + if (FL_TEST(rklass, FL_SINGLETON)) { + rb_raise(rb_eTypeError, "cannot bind singleton method to a different class"); + } + if (FL_TEST(mod, FL_SINGLETON) && + st_lookup(RCLASS(mod)->m_tbl, method->oid, 0)) { + rb_raise(rb_eTypeError, "method `%s' overridden", rb_id2name(method->oid)); + } + if (RCLASS(rklass)->super && !rb_mod_le(mod, rklass)) { + rb_raise(rb_eTypeError, "bind argument must be a subclass of %s", + rb_class2name(rklass)); + } + } + node = method->body; } else if (RDATA(body)->dmark == (RUBY_DATA_FUNC)blk_mark) { Index: node.h =================================================================== RCS file: /cvs/ruby/src/ruby/node.h,v retrieving revision 1.52 diff -u -2 -p -r1.52 node.h --- node.h 22 Jan 2004 08:31:33 -0000 1.52 +++ node.h 10 Feb 2004 02:27:40 -0000 @@ -119,5 +119,4 @@ enum node_type { NODE_ALLOCA, #endif - NODE_DMETHOD, NODE_BMETHOD, NODE_MEMO, @@ -336,5 +335,4 @@ typedef struct RNode { #define NEW_PREEXE(b) NEW_SCOPE(b) #define NEW_POSTEXE() NEW_NODE(NODE_POSTEXE,0,0,0) -#define NEW_DMETHOD(b) NEW_NODE(NODE_DMETHOD,0,0,b) #define NEW_BMETHOD(b) NEW_NODE(NODE_BMETHOD,0,0,b) #define NEW_ATTRASGN(r,m,a) NEW_NODE(NODE_ATTRASGN,r,m,a)
-- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦