From: Akinori MUSHA Date: 2010-06-27T00:09:34+09:00 Subject: [ruby-dev:41739] Re: respond_to?() returns true --pgp-sign-Multipart_Sun_Jun_27_00:09:33_2010-1 Content-Type: text/plain; charset=ISO-2022-JP At Wed, 24 Feb 2010 01:25:45 +0900, matz wrote: > In message "Re: [ruby-dev:40465] Re: respond_to?() returns true" > on Wed, 24 Feb 2010 01:12:55 +0900, "Akinori MUSHA" writes: > > |> 前のメールでも書いたように method_missing による偽陰性は存在 > |> するので、本質的には指摘は当たっているのですが。で、偽陰性の > |> 排除についてですが、ちょっと考えた結果、賛成します。 > | > | ご検討ありがとうございます。賛成くださるのは偽陽性の排除ですよね。 > > あ、そうです。protectedに対してrespond_to?が真を返しているの > を偽に統一するということですね。  だいぶ間が空いてしまいましたが、これでどうでしょうか。 Index: vm_method.c =================================================================== --- vm_method.c (revision 28446) +++ vm_method.c (working copy) @@ -566,8 +566,9 @@ rb_method_boundp(VALUE klass, ID id, int rb_method_entry_t *me = rb_method_entry(klass, id); if (me != 0) { - if ((ex & ~NOEX_RESPONDS) && (me->flag & NOEX_PRIVATE)) { - return FALSE; + if ((ex & NOEX_RESPONDS) && (me->flag & NOEX_PROTECTED) || + (ex & ~NOEX_RESPONDS) && (me->flag & NOEX_PRIVATE)) { + return 0; } if (!me->def) return 0; if (me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) { Index: test/ruby/test_method.rb =================================================================== --- test/ruby/test_method.rb (revision 28446) +++ test/ruby/test_method.rb (working copy) @@ -39,6 +39,20 @@ class TestMethod < Test::Unit::TestCase def meth; end end + def mv1() end + def mv2() end + private :mv2 + def mv3() end + protected :mv3 + + class Visibility + def mv1() end + def mv2() end + private :mv2 + def mv3() end + protected :mv3 + end + def test_arity assert_equal(0, method(:m0).arity) assert_equal(1, method(:m1).arity) @@ -345,4 +359,48 @@ class TestMethod < Test::Unit::TestCase obj.extend(m) assert_equal([:m1, :a], obj.public_methods(false), bug) end + + def test_visibility + assert_equal('method', defined?(mv1)) + assert_equal('method', defined?(mv2)) + assert_equal('method', defined?(mv3)) + + assert_equal('method', defined?(self.mv1)) + assert_equal(nil, defined?(self.mv2)) + assert_equal('method', defined?(self.mv3)) + + assert_equal(true, respond_to?(:mv1)) + assert_equal(false, respond_to?(:mv2)) + assert_equal(false, respond_to?(:mv3)) + + assert_nothing_raised { mv1 } + assert_nothing_raised { mv2 } + assert_nothing_raised { mv3 } + + assert_nothing_raised { self.mv1 } + assert_raise(NoMethodError) { self.mv2 } + assert_nothing_raised { self.mv3 } + + v = Visibility.new + + assert_equal('method', defined?(v.mv1)) + assert_equal(nil, defined?(v.mv2)) + assert_equal(nil, defined?(v.mv3)) + + assert_equal(true, v.respond_to?(:mv1)) + assert_equal(false, v.respond_to?(:mv2)) + assert_equal(false, v.respond_to?(:mv3)) + + assert_nothing_raised { v.mv1 } + assert_raise(NoMethodError) { v.mv2 } + assert_raise(NoMethodError) { v.mv3 } + + assert_nothing_raised { v.__send__(:mv1) } + assert_nothing_raised { v.__send__(:mv2) } + assert_nothing_raised { v.__send__(:mv3) } + + assert_nothing_raised { v.instance_eval { mv1 } } + assert_nothing_raised { v.instance_eval { mv2 } } + assert_nothing_raised { v.instance_eval { mv3 } } + end end -- Akinori MUSHA / http://akinori.org/ --pgp-sign-Multipart_Sun_Jun_27_00:09:33_2010-1 Content-Type: application/pgp-signature Content-Transfer-Encoding: 7bit -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (FreeBSD) iEYEABECAAYFAkwmGC0ACgkQkgvvx5/Z4e7CIQCfWYGLwSGWx0dKuSqA3DRkM/K4 OaoAn1oh8VnfPPDBlKxHLtXfdWjjO8cc =NJRk -----END PGP SIGNATURE----- --pgp-sign-Multipart_Sun_Jun_27_00:09:33_2010-1--