diff options
author | nagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-03-20 15:53:38 +0000 |
---|---|---|
committer | nagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-03-20 15:53:38 +0000 |
commit | 9e7b5784180e29b258c99fd36639b5221d427287 (patch) | |
tree | e055f4d1e6d183fd14d11d20fd49bd3ce17f09f5 | |
parent | ab2e7357bd27b5139415bf823c2780bc8273eb83 (diff) |
merge revision(s) 58245,60127: [Backport #13973]
Refactored using Method#owner.
proc.c: super_method of included method
* proc.c (method_super_method): search the next super method along
the included ancestor chain. [ruby-core:83114] [Bug #13973]
* vm_method.c (rb_callable_method_entry_without_refinements):
return the defined class.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_4@62865 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | lib/pp.rb | 4 | ||||
-rw-r--r-- | method.h | 8 | ||||
-rw-r--r-- | proc.c | 37 | ||||
-rw-r--r-- | test/ruby/test_method.rb | 10 | ||||
-rw-r--r-- | version.h | 6 | ||||
-rw-r--r-- | vm_args.c | 2 | ||||
-rw-r--r-- | vm_insnhelper.c | 7 | ||||
-rw-r--r-- | vm_method.c | 28 |
8 files changed, 58 insertions, 44 deletions
@@ -311,7 +311,7 @@ class PP < PrettyPrint inspect_method = method_method.call(:inspect) rescue NameError end - if inspect_method && /\(Kernel\)#/ !~ inspect_method.inspect + if inspect_method && inspect_method.owner != Kernel q.text self.inspect elsif !inspect_method && self.respond_to?(:inspect) q.text self.inspect @@ -345,7 +345,7 @@ class PP < PrettyPrint # However, doing this requires that every class that #inspect is called on # implement #pretty_print, or a RuntimeError will be raised. def pretty_print_inspect - if /\(PP::ObjectMixin\)#/ =~ Object.instance_method(:method).bind(self).call(:pretty_print).inspect + if Object.instance_method(:method).bind(self).call(:pretty_print).owner == PP::ObjectMixin raise "pretty_print is not overridden for #{self.class}" end PP.singleline_pp(self, ''.dup) @@ -184,13 +184,13 @@ rb_method_entry_t *rb_method_entry_create(ID called_id, VALUE klass, rb_method_v const rb_method_entry_t *rb_method_entry_at(VALUE obj, ID id); const rb_method_entry_t *rb_method_entry(VALUE klass, ID id); -const rb_method_entry_t *rb_method_entry_with_refinements(VALUE klass, ID id); -const rb_method_entry_t *rb_method_entry_without_refinements(VALUE klass, ID id); +const rb_method_entry_t *rb_method_entry_with_refinements(VALUE klass, ID id, VALUE *defined_class); +const rb_method_entry_t *rb_method_entry_without_refinements(VALUE klass, ID id, VALUE *defined_class); const rb_method_entry_t *rb_resolve_refined_method(VALUE refinements, const rb_method_entry_t *me); const rb_callable_method_entry_t *rb_callable_method_entry(VALUE klass, ID id); -const rb_callable_method_entry_t *rb_callable_method_entry_with_refinements(VALUE klass, ID id); -const rb_callable_method_entry_t *rb_callable_method_entry_without_refinements(VALUE klass, ID id); +const rb_callable_method_entry_t *rb_callable_method_entry_with_refinements(VALUE klass, ID id, VALUE *defined_class); +const rb_callable_method_entry_t *rb_callable_method_entry_without_refinements(VALUE klass, ID id, VALUE *defined_class); const rb_callable_method_entry_t *rb_resolve_refined_method_callable(VALUE refinements, const rb_callable_method_entry_t *me); int rb_method_entry_arity(const rb_method_entry_t *me); @@ -29,6 +29,7 @@ const rb_cref_t *rb_vm_cref_in_context(VALUE self, VALUE cbase); struct METHOD { const VALUE recv; const VALUE klass; + const VALUE iclass; const rb_method_entry_t * const me; /* for bound methods, `me' should be rb_callable_method_entry_t * */ }; @@ -1326,6 +1327,7 @@ bm_mark(void *ptr) struct METHOD *data = ptr; rb_gc_mark(data->recv); rb_gc_mark(data->klass); + rb_gc_mark(data->iclass); rb_gc_mark((VALUE)data->me); } @@ -1393,7 +1395,7 @@ mnew_missing(VALUE klass, VALUE obj, ID id, VALUE mclass) } static VALUE -mnew_internal(const rb_method_entry_t *me, VALUE klass, +mnew_internal(const rb_method_entry_t *me, VALUE klass, VALUE iclass, VALUE obj, ID id, VALUE mclass, int scope, int error) { struct METHOD *data; @@ -1419,24 +1421,21 @@ mnew_internal(const rb_method_entry_t *me, VALUE klass, if (me->defined_class) { VALUE klass = RCLASS_SUPER(RCLASS_ORIGIN(me->defined_class)); id = me->def->original_id; - me = (rb_method_entry_t *)rb_callable_method_entry_without_refinements(klass, id); + me = (rb_method_entry_t *)rb_callable_method_entry_without_refinements(klass, id, &iclass); } else { VALUE klass = RCLASS_SUPER(me->owner); id = me->def->original_id; - me = rb_method_entry_without_refinements(klass, id); + me = rb_method_entry_without_refinements(klass, id, &iclass); } goto again; } - while (klass != me->owner && (FL_TEST(klass, FL_SINGLETON) || RB_TYPE_P(klass, T_ICLASS))) { - klass = RCLASS_SUPER(klass); - } - method = TypedData_Make_Struct(mclass, struct METHOD, &method_data_type, data); RB_OBJ_WRITE(method, &data->recv, obj); RB_OBJ_WRITE(method, &data->klass, klass); + RB_OBJ_WRITE(method, &data->iclass, iclass); RB_OBJ_WRITE(method, &data->me, me); OBJ_INFECT(method, klass); @@ -1444,24 +1443,25 @@ mnew_internal(const rb_method_entry_t *me, VALUE klass, } static VALUE -mnew_from_me(const rb_method_entry_t *me, VALUE klass, +mnew_from_me(const rb_method_entry_t *me, VALUE klass, VALUE iclass, VALUE obj, ID id, VALUE mclass, int scope) { - return mnew_internal(me, klass, obj, id, mclass, scope, TRUE); + return mnew_internal(me, klass, iclass, obj, id, mclass, scope, TRUE); } static VALUE mnew(VALUE klass, VALUE obj, ID id, VALUE mclass, int scope) { const rb_method_entry_t *me; + VALUE iclass = Qnil; if (obj == Qundef) { /* UnboundMethod */ - me = rb_method_entry_without_refinements(klass, id); + me = rb_method_entry_without_refinements(klass, id, &iclass); } else { - me = (rb_method_entry_t *)rb_callable_method_entry_without_refinements(klass, id); + me = (rb_method_entry_t *)rb_callable_method_entry_without_refinements(klass, id, &iclass); } - return mnew_from_me(me, klass, obj, id, mclass, scope); + return mnew_from_me(me, klass, iclass, obj, id, mclass, scope); } static inline VALUE @@ -1785,7 +1785,7 @@ rb_obj_singleton_method(VALUE obj, VALUE vid) vid = ID2SYM(id); goto undef; } - return mnew_from_me(me, klass, obj, id, rb_cMethod, FALSE); + return mnew_from_me(me, klass, klass, obj, id, rb_cMethod, FALSE); } /* @@ -2706,15 +2706,18 @@ static VALUE method_super_method(VALUE method) { const struct METHOD *data; - VALUE super_class; + VALUE super_class, iclass; + ID mid; const rb_method_entry_t *me; TypedData_Get_Struct(method, struct METHOD, &method_data_type, data); - super_class = RCLASS_SUPER(RCLASS_ORIGIN(method_entry_defined_class(data->me))); + iclass = data->iclass; + super_class = RCLASS_SUPER(RCLASS_ORIGIN(iclass)); + mid = data->me->called_id; if (!super_class) return Qnil; - me = (rb_method_entry_t *)rb_callable_method_entry_without_refinements(super_class, data->me->called_id); + me = (rb_method_entry_t *)rb_callable_method_entry_without_refinements(super_class, mid, &iclass); if (!me) return Qnil; - return mnew_internal(me, super_class, data->recv, data->me->called_id, rb_obj_class(method), FALSE, FALSE); + return mnew_internal(me, me->owner, iclass, data->recv, mid, rb_obj_class(method), FALSE, FALSE); } /* diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb index 1f8b86acdc..7f173e86ac 100644 --- a/test/ruby/test_method.rb +++ b/test/ruby/test_method.rb @@ -873,6 +873,16 @@ class TestMethod < Test::Unit::TestCase m = m.super_method assert_equal(c1, m.owner, Feature9781) assert_same(o, m.receiver, Feature9781) + + c1 = Class.new {def foo; end} + c2 = Class.new(c1) {include m1; include m2} + m = c2.instance_method(:foo) + assert_equal(m2, m.owner) + m = m.super_method + assert_equal(m1, m.owner) + m = m.super_method + assert_equal(c1, m.owner) + assert_nil(m.super_method) end def test_super_method_removed @@ -1,10 +1,10 @@ #define RUBY_VERSION "2.4.4" -#define RUBY_RELEASE_DATE "2018-03-20" -#define RUBY_PATCHLEVEL 273 +#define RUBY_RELEASE_DATE "2018-03-21" +#define RUBY_PATCHLEVEL 274 #define RUBY_RELEASE_YEAR 2018 #define RUBY_RELEASE_MONTH 3 -#define RUBY_RELEASE_DAY 20 +#define RUBY_RELEASE_DAY 21 #include "ruby/version.h" @@ -803,7 +803,7 @@ refine_sym_proc_call(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)) } obj = *argv++; mid = SYM2ID(callback_arg); - me = rb_callable_method_entry_with_refinements(CLASS_OF(obj), mid); + me = rb_callable_method_entry_with_refinements(CLASS_OF(obj), mid, NULL); th = GET_THREAD(); if (!NIL_P(blockarg)) { vm_passed_block_handler_set(th, blockarg); diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 57f1859c2a..5e3abc9d80 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -1336,7 +1336,8 @@ check_match(VALUE pattern, VALUE target, enum vm_check_match_type type) } /* fall through */ case VM_CHECKMATCH_TYPE_CASE: { - const rb_callable_method_entry_t *me = rb_callable_method_entry_with_refinements(CLASS_OF(pattern), idEqq); + const rb_callable_method_entry_t *me = + rb_callable_method_entry_with_refinements(CLASS_OF(pattern), idEqq, NULL); if (me) { return vm_call0(GET_THREAD(), pattern, idEqq, 1, &target, me); } @@ -1972,7 +1973,7 @@ vm_call_opt_send(rb_thread_t *th, rb_control_frame_t *reg_cfp, struct rb_calling DEC_SP(1); } - cc->me = rb_callable_method_entry_with_refinements(CLASS_OF(calling->recv), ci->mid); + cc->me = rb_callable_method_entry_with_refinements(CLASS_OF(calling->recv), ci->mid, NULL); ci->flag = VM_CALL_FCALL | VM_CALL_OPT_SEND; return vm_call_method(th, reg_cfp, calling, ci, cc); } @@ -2015,7 +2016,7 @@ vm_call_method_missing(rb_thread_t *th, rb_control_frame_t *reg_cfp, struct rb_c cc_entry = *orig_cc; cc_entry.me = rb_callable_method_entry_without_refinements(CLASS_OF(calling->recv), - idMethodMissing); + idMethodMissing, NULL); cc = &cc_entry; calling->argc = argc; diff --git a/vm_method.c b/vm_method.c index e0088d0016..a5c83ab0f6 100644 --- a/vm_method.c +++ b/vm_method.c @@ -887,31 +887,31 @@ method_entry_resolve_refinement(VALUE klass, ID id, int with_refinement, VALUE * } const rb_method_entry_t * -rb_method_entry_with_refinements(VALUE klass, ID id) +rb_method_entry_with_refinements(VALUE klass, ID id, VALUE *defined_class_ptr) { - return method_entry_resolve_refinement(klass, id, TRUE, NULL); + return method_entry_resolve_refinement(klass, id, TRUE, defined_class_ptr); } const rb_callable_method_entry_t * -rb_callable_method_entry_with_refinements(VALUE klass, ID id) +rb_callable_method_entry_with_refinements(VALUE klass, ID id, VALUE *defined_class_ptr) { - VALUE defined_class; - const rb_method_entry_t *me = method_entry_resolve_refinement(klass, id, TRUE, &defined_class); - return prepare_callable_method_entry(defined_class, id, me); + VALUE defined_class, *dcp = defined_class_ptr ? defined_class_ptr : &defined_class; + const rb_method_entry_t *me = method_entry_resolve_refinement(klass, id, TRUE, dcp); + return prepare_callable_method_entry(*dcp, id, me); } const rb_method_entry_t * -rb_method_entry_without_refinements(VALUE klass, ID id) +rb_method_entry_without_refinements(VALUE klass, ID id, VALUE *defined_class_ptr) { - return method_entry_resolve_refinement(klass, id, FALSE, NULL); + return method_entry_resolve_refinement(klass, id, FALSE, defined_class_ptr); } const rb_callable_method_entry_t * -rb_callable_method_entry_without_refinements(VALUE klass, ID id) +rb_callable_method_entry_without_refinements(VALUE klass, ID id, VALUE *defined_class_ptr) { - VALUE defined_class; - const rb_method_entry_t *me = method_entry_resolve_refinement(klass, id, FALSE, &defined_class); - return prepare_callable_method_entry(defined_class, id, me); + VALUE defined_class, *dcp = defined_class_ptr ? defined_class_ptr : &defined_class; + const rb_method_entry_t *me = method_entry_resolve_refinement(klass, id, FALSE, dcp); + return prepare_callable_method_entry(*dcp, id, me); } static const rb_method_entry_t * @@ -1091,7 +1091,7 @@ rb_export_method(VALUE klass, ID name, rb_method_visibility_t visi) int rb_method_boundp(VALUE klass, ID id, int ex) { - const rb_method_entry_t *me = rb_method_entry_without_refinements(klass, id); + const rb_method_entry_t *me = rb_method_entry_without_refinements(klass, id, NULL); if (me != 0) { if ((ex & ~BOUND_RESPONDS) && @@ -1331,7 +1331,7 @@ check_definition(VALUE mod, VALUE mid, rb_method_visibility_t visi) const rb_method_entry_t *me; ID id = rb_check_id(&mid); if (!id) return Qfalse; - me = rb_method_entry_without_refinements(mod, id); + me = rb_method_entry_without_refinements(mod, id, NULL); if (me) { if (METHOD_ENTRY_VISI(me) == visi) return Qtrue; } |