ruby-changes:63661
From: Nobuyoshi <ko1@a...>
Date: Fri, 20 Nov 2020 16:05:03 +0900 (JST)
Subject: [ruby-changes:63661] fac2498e02 (master): [Bug #11213] let defined?(super) call respond_to_missing?
https://git.ruby-lang.org/ruby.git/commit/?id=fac2498e02 From fac2498e0299f13dffe4f09a7dd7657fb49bf643 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada <nobu@r...> Date: Tue, 17 Nov 2020 21:17:19 +0900 Subject: [Bug #11213] let defined?(super) call respond_to_missing? diff --git a/internal/vm.h b/internal/vm.h index 5af422e..d146bc6 100644 --- a/internal/vm.h +++ b/internal/vm.h @@ -99,7 +99,7 @@ MJIT_SYMBOL_EXPORT_END https://github.com/ruby/ruby/blob/trunk/internal/vm.h#L99 /* vm_method.c */ struct rb_execution_context_struct; MJIT_SYMBOL_EXPORT_BEGIN -int rb_ec_obj_respond_to(struct rb_execution_context_struct *ec, VALUE obj, ID id, int priv); +int rb_ec_obj_respond_to(struct rb_execution_context_struct *ec, VALUE klass, VALUE obj, ID id, int priv); MJIT_SYMBOL_EXPORT_END /* vm_dump.c */ diff --git a/test/ruby/test_defined.rb b/test/ruby/test_defined.rb index b22db70..87f0205 100644 --- a/test/ruby/test_defined.rb +++ b/test/ruby/test_defined.rb @@ -302,6 +302,39 @@ class TestDefined < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_defined.rb#L302 assert_nil(defined?(TestDefined::Object)) end + def test_super_with_method_missing + c0 = EnvUtil.labeled_class("C0") do + attr_reader :calls + + def initialize + @calls = [] + end + + def method_missing(*args) + @calls << [:method_missing, *args] + end + + def respond_to_missing?(*args) + @calls << [:respond_to_missing?, *args] + true + end + end + + c1 = EnvUtil.labeled_class("C1", c0) do + def foo + super + defined?(super) + end + end + + c = c1.new + assert_not_nil(c.foo) + assert_equal([ + [:method_missing, :foo], + [:respond_to_missing?, :foo, true], + ], c.calls) + end + class RefinedClass end diff --git a/vm_insnhelper.c b/vm_insnhelper.c index f902a65..4f5d18a 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -3770,7 +3770,7 @@ vm_defined(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t op_ https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L3770 } case DEFINED_FUNC: klass = CLASS_OF(v); - if (rb_ec_obj_respond_to(ec, v, SYM2ID(obj), TRUE)) { + if (rb_ec_obj_respond_to(ec, klass, v, SYM2ID(obj), TRUE)) { expr_type = DEFINED_METHOD; } break; @@ -3811,7 +3811,7 @@ vm_defined(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t op_ https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L3811 VALUE klass = vm_search_normal_superclass(me->defined_class); ID id = me->def->original_id; - if (rb_method_boundp(klass, id, 0)) { + if (rb_ec_obj_respond_to(ec, klass, GET_SELF(), id, TRUE)) { expr_type = DEFINED_ZSUPER; } } diff --git a/vm_method.c b/vm_method.c index ec7d226..a143db7 100644 --- a/vm_method.c +++ b/vm_method.c @@ -2322,9 +2322,8 @@ basic_obj_respond_to_missing(rb_execution_context_t *ec, VALUE klass, VALUE obj, https://github.com/ruby/ruby/blob/trunk/vm_method.c#L2322 } static inline int -basic_obj_respond_to(rb_execution_context_t *ec, VALUE obj, ID id, int pub) +basic_obj_respond_to(rb_execution_context_t *ec, VALUE klass, VALUE obj, ID id, int pub) { - VALUE klass = CLASS_OF(obj); VALUE ret; switch (rb_method_boundp(klass, id, pub|BOUND_RESPONDS)) { @@ -2393,15 +2392,14 @@ int https://github.com/ruby/ruby/blob/trunk/vm_method.c#L2392 rb_obj_respond_to(VALUE obj, ID id, int priv) { rb_execution_context_t *ec = GET_EC(); - return rb_ec_obj_respond_to(ec, obj, id, priv); + return rb_ec_obj_respond_to(ec, CLASS_OF(obj), obj, id, priv); } int -rb_ec_obj_respond_to(rb_execution_context_t *ec, VALUE obj, ID id, int priv) +rb_ec_obj_respond_to(rb_execution_context_t *ec, VALUE klass, VALUE obj, ID id, int priv) { - VALUE klass = CLASS_OF(obj); int ret = vm_respond_to(ec, klass, obj, id, priv); - if (ret == -1) ret = basic_obj_respond_to(ec, obj, id, !priv); + if (ret == -1) ret = basic_obj_respond_to(ec, klass, obj, id, !priv); return ret; } @@ -2446,7 +2444,7 @@ obj_respond_to(int argc, VALUE *argv, VALUE obj) https://github.com/ruby/ruby/blob/trunk/vm_method.c#L2444 if (ret == Qundef) ret = Qfalse; return ret; } - if (basic_obj_respond_to(ec, obj, id, !RTEST(priv))) + if (basic_obj_respond_to(ec, CLASS_OF(obj), obj, id, !RTEST(priv))) return Qtrue; return Qfalse; } -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/