diff --git a/ChangeLog b/ChangeLog index b882383485..6c4dc09a04 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +Mon Oct 5 00:09:57 2009 Yukihiro Matsumoto + + * vm_method.c (basic_obj_respond_to): should not call + #respond_to_missing? for not implemented methods. + [ruby-core:25909] + + * vm_method.c (rb_method_boundp): returns exceptional value 2 for + not-implemented methods when called from #respond_to? (specifies + by new contant NOEX_RESPONDS). + + * method.h (enum): new constant NOEX_RESPONDS added. + Sun Oct 4 22:16:29 2009 Takeyuki FUJIOKA * lib/cgi/cookie.rb: add default value to @@accept_charset diff --git a/method.h b/method.h index 11fd6bfef8..177d7bc677 100644 --- a/method.h +++ b/method.h @@ -21,7 +21,8 @@ typedef enum { NOEX_UNDEF = NOEX_NOSUPER, NOEX_MODFUNC = 0x12, NOEX_SUPER = 0x20, - NOEX_VCALL = 0x40 + NOEX_VCALL = 0x40, + NOEX_RESPONDS = 0x80 } rb_method_flag_t; #define NOEX_SAFE(n) ((int)((n) >> 8) & 0x0F) diff --git a/vm_method.c b/vm_method.c index ec381c40d7..a31fb8b5ac 100644 --- a/vm_method.c +++ b/vm_method.c @@ -515,12 +515,14 @@ rb_method_boundp(VALUE klass, ID id, int ex) if (ex && (me->flag & NOEX_PRIVATE)) { return FALSE; } - if (!me->def || me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) { - return FALSE; + if (!me->def) return 0; + if (me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) { + if (ex & NOEX_RESPONDS) return 2; + return 0; } - return TRUE; + return 1; } - return FALSE; + return 0; } void @@ -1151,13 +1153,14 @@ basic_obj_respond_to(VALUE obj, ID id, int pub) { VALUE klass = CLASS_OF(obj); - if (!rb_method_boundp(klass, id, pub)) { - if (!rb_method_basic_definition_p(klass, respond_to_missing)) { - return RTEST(rb_funcall(obj, respond_to_missing, pub ? 1 : 2, ID2SYM(id), Qtrue)); - } + switch (rb_method_boundp(klass, id, pub|NOEX_RESPONDS)) { + case 2: return FALSE; + case 0: + return RTEST(rb_funcall(obj, respond_to_missing, pub ? 1 : 2, ID2SYM(id), Qtrue)); + default: + return TRUE; } - return TRUE; } int