1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* 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
This commit is contained in:
shugo 2015-02-03 06:26:48 +00:00
parent 338bd4cc65
commit 525f515f9a
3 changed files with 71 additions and 1 deletions

View file

@ -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

View file

@ -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)

View file

@ -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);
}