зеркало из https://github.com/github/ruby.git
* 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:
Родитель
338bd4cc65
Коммит
525f515f9a
12
ChangeLog
12
ChangeLog
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче