ruby-changes:33486
From: nobu <ko1@a...>
Date: Fri, 11 Apr 2014 15:05:35 +0900 (JST)
Subject: [ruby-changes:33486] nobu:r45565 (trunk): proc.c: fix super in bound UnboundMethod
nobu 2014-04-11 15:05:28 +0900 (Fri, 11 Apr 2014) New Revision: 45565 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=45565 Log: proc.c: fix super in bound UnboundMethod * proc.c (rb_method_call_with_block, umethod_bind): call with IClass including the module for a module instance method. [ruby-core:61936] [Bug #9721] * vm_insnhelper.c (vm_search_super_method): allow bound UnboundMethod case. Modified files: trunk/ChangeLog trunk/proc.c trunk/test/ruby/test_super.rb trunk/vm_insnhelper.c Index: ChangeLog =================================================================== --- ChangeLog (revision 45564) +++ ChangeLog (revision 45565) @@ -1,3 +1,12 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Fri Apr 11 15:05:26 2014 Nobuyoshi Nakada <nobu@r...> + + * proc.c (rb_method_call_with_block, umethod_bind): call with + IClass including the module for a module instance method. + [ruby-core:61936] [Bug #9721] + + * vm_insnhelper.c (vm_search_super_method): allow bound + UnboundMethod case. + Fri Apr 11 12:02:30 2014 NARUSE, Yui <naruse@r...> * addr2line.c (rb_dump_backtrace_with_lines): set base address Index: proc.c =================================================================== --- proc.c (revision 45564) +++ proc.c (revision 45565) @@ -1891,6 +1891,7 @@ rb_method_call_with_block(int argc, VALU https://github.com/ruby/ruby/blob/trunk/proc.c#L1891 if ((state = EXEC_TAG()) == 0) { rb_thread_t *th = GET_THREAD(); rb_block_t *block = 0; + VALUE defined_class; if (!NIL_P(pass_procval)) { rb_proc_t *pass_proc; @@ -1900,7 +1901,9 @@ rb_method_call_with_block(int argc, VALU https://github.com/ruby/ruby/blob/trunk/proc.c#L1901 th->passed_block = block; VAR_INITIALIZED(data); - result = rb_vm_call(th, data->recv, data->id, argc, argv, data->me, data->defined_class); + defined_class = data->defined_class; + if (BUILTIN_TYPE(defined_class) == T_MODULE) defined_class = data->rclass; + result = rb_vm_call(th, data->recv, data->id, argc, argv, data->me, defined_class); } POP_TAG(); if (safe >= 0) @@ -2006,6 +2009,7 @@ umethod_bind(VALUE method, VALUE recv) https://github.com/ruby/ruby/blob/trunk/proc.c#L2009 { struct METHOD *data, *bound; VALUE methclass; + VALUE rclass; TypedData_Get_Struct(method, struct METHOD, &method_data_type, data); @@ -2027,8 +2031,12 @@ umethod_bind(VALUE method, VALUE recv) https://github.com/ruby/ruby/blob/trunk/proc.c#L2031 bound->me = ALLOC(rb_method_entry_t); *bound->me = *data->me; if (bound->me->def) bound->me->def->alias_count++; + rclass = CLASS_OF(recv); + if (BUILTIN_TYPE(bound->defined_class) == T_MODULE) { + rclass = rb_include_class_new(methclass, rclass); + } bound->recv = recv; - bound->rclass = CLASS_OF(recv); + bound->rclass = rclass; data->ume = ALLOC(struct unlinked_method_entry_list_entry); return method; Index: vm_insnhelper.c =================================================================== --- vm_insnhelper.c (revision 45564) +++ vm_insnhelper.c (revision 45565) @@ -2034,6 +2034,7 @@ vm_search_super_method(rb_thread_t *th, https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L2034 } if (BUILTIN_TYPE(current_defined_class) != T_MODULE && + BUILTIN_TYPE(current_defined_class) != T_ICLASS && /* bound UnboundMethod */ !FL_TEST(current_defined_class, RMODULE_INCLUDED_INTO_REFINEMENT) && !rb_obj_is_kind_of(ci->recv, current_defined_class)) { VALUE m = RB_TYPE_P(current_defined_class, T_ICLASS) ? Index: test/ruby/test_super.rb =================================================================== --- test/ruby/test_super.rb (revision 45564) +++ test/ruby/test_super.rb (revision 45565) @@ -452,4 +452,28 @@ class TestSuper < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_super.rb#L452 m.call end end + + def test_super_in_module_unbound_method + bug9721 = '[ruby-core:61936] [Bug #9721]' + + a = Module.new do + def foo(result) + result << "A" + end + end + + b = Module.new do + def foo(result) + result << "B" + super + end + end + + m = b.instance_method(:foo).bind(Object.new.extend(a)) + result = [] + assert_nothing_raised(NoMethodError, bug9721) do + m.call(result) + end + assert_equal(%w[B A], result, bug9721) + end end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/