From c42cf2358c791e43afbb2ef8574c1de62daab9dc Mon Sep 17 00:00:00 2001 From: naruse Date: Thu, 19 Feb 2015 07:19:33 +0000 Subject: merge revision(s) 49480,49493: [Backport #10765] * vm_method.c (remove_method): When remove refined method, raise a NameError if the method is not defined in refined class. But if the method is defined in refined class, it should keep refined method and remove original method. Patch by Seiei Higa. [ruby-core:67722] [Bug #10765] * class.c (method_entry_i, class_instance_method_list, rb_obj_singleton_methods): should not include methods of superclasses if recur is false. [ruby-dev:48854] [Bug #10826] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_2@49647 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 18 +++++++++++++++ test/ruby/test_refinement.rb | 52 ++++++++++++++++++++++++++++++++++++++++++++ version.h | 2 +- vm_method.c | 8 ++++++- 4 files changed, 78 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 544f01d469..322cf57e13 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +Thu Feb 19 16:14:04 2015 Shugo Maeda + + * class.c (method_entry_i, class_instance_method_list, + rb_obj_singleton_methods): should not include methods of + superclasses if recur is false. [ruby-dev:48854] [Bug #10826] + +Thu Feb 19 16:14:04 2015 Shugo Maeda + + * vm_method.c (remove_method): When remove refined + method, raise a NameError if the method is not + defined in refined class. + + But if the method is defined in refined class, + it should keep refined method and remove original + method. + + Patch by Seiei Higa. [ruby-core:67722] [Bug #10765] + Thu Feb 19 16:07:03 2015 Seiei Higa * proc.c (rb_obj_singleton_method): Kernel#singleton_method should diff --git a/test/ruby/test_refinement.rb b/test/ruby/test_refinement.rb index 5837f45d0f..3d703e5a3b 100644 --- a/test/ruby/test_refinement.rb +++ b/test/ruby/test_refinement.rb @@ -1310,6 +1310,58 @@ class TestRefinement < Test::Unit::TestCase end; end + def test_remove_refined_method + assert_separately([], <<-"end;") + bug10765 = '[ruby-core:67722] [Bug #10765]' + + class C + def foo + "C#foo" + end + end + + module RefinementBug + refine C do + def foo + "RefinementBug#foo" + end + end + end + + using RefinementBug + + class C + remove_method :foo + end + + assert_equal("RefinementBug#foo", C.new.foo, bug10765) + end; + end + + def test_remove_undefined_refined_method + assert_separately([], <<-"end;") + bug10765 = '[ruby-core:67722] [Bug #10765]' + + class C + end + + module RefinementBug + refine C do + def foo + end + end + end + + using RefinementBug + + assert_raise(NameError, bug10765) { + class C + remove_method :foo + end + } + end; + end + module NotIncludeSuperclassMethod class X def foo diff --git a/version.h b/version.h index 3f7f856290..9eaea6b815 100644 --- a/version.h +++ b/version.h @@ -1,6 +1,6 @@ #define RUBY_VERSION "2.2.0" #define RUBY_RELEASE_DATE "2015-02-19" -#define RUBY_PATCHLEVEL 57 +#define RUBY_PATCHLEVEL 58 #define RUBY_RELEASE_YEAR 2015 #define RUBY_RELEASE_MONTH 2 diff --git a/vm_method.c b/vm_method.c index d016fc5c0e..bb13d12b1f 100644 --- a/vm_method.c +++ b/vm_method.c @@ -766,10 +766,12 @@ remove_method(VALUE klass, ID mid) if (!st_lookup(RCLASS_M_TBL(klass), mid, &data) || !(me = (rb_method_entry_t *)data) || - (!me->def || me->def->type == VM_METHOD_TYPE_UNDEF)) { + (!me->def || me->def->type == VM_METHOD_TYPE_UNDEF) || + UNDEFINED_REFINED_METHOD_P(me->def)) { rb_name_error(mid, "method `%"PRIsVALUE"' not defined in %"PRIsVALUE, rb_id2str(mid), rb_class_path(klass)); } + key = (st_data_t)mid; st_delete(RCLASS_M_TBL(klass), &key, &data); @@ -777,6 +779,10 @@ remove_method(VALUE klass, ID mid) rb_clear_method_cache_by_class(klass); rb_unlink_method_entry(me); + if (me->def->type == VM_METHOD_TYPE_REFINED) { + rb_add_refined_method_entry(klass, mid); + } + CALL_METHOD_HOOK(self, removed, mid); } -- cgit v1.2.3