diff options
author | shugo <shugo@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-02-03 06:26:48 +0000 |
---|---|---|
committer | shugo <shugo@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-02-03 06:26:48 +0000 |
commit | 525f515f9ac593f11ad52a301d7594bcc52a3062 (patch) | |
tree | ac39ccbbef8477e3bdaf973af5df0441187be7c6 | |
parent | 338bd4cc651964e3901a4ddaa52667ddb47a55cf (diff) | |
download | ruby-525f515f9ac593f11ad52a301d7594bcc52a3062.tar.gz |
* 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]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@49480 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 12 | ||||
-rw-r--r-- | test/ruby/test_refinement.rb | 52 | ||||
-rw-r--r-- | vm_method.c | 8 |
3 files changed, 71 insertions, 1 deletions
@@ -1,3 +1,15 @@ +Tue Feb 3 15:23:58 2015 Shugo Maeda <shugo@ruby-lang.org> + + * 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] + Tue Feb 3 14:04:47 2015 Nobuyoshi Nakada <nobu@ruby-lang.org> * dir.c (glob_helper): obtain real name with FindFirstFile API diff --git a/test/ruby/test_refinement.rb b/test/ruby/test_refinement.rb index df162545d5..cb7c53f98d 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 + private def eval_using(mod, s) diff --git a/vm_method.c b/vm_method.c index b2cff6f13d..8ad2b72c21 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); } |