* 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
Родитель 338bd4cc65
Коммит 525f515f9a
3 изменённых файлов: 71 добавлений и 1 удалений

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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