summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-11-22 08:29:02 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-11-22 08:29:02 +0000
commit16a642c3315832992b2af401a45b02451c23f165 (patch)
tree1174cbabea6aa7eadff084d2df8a110707d8b12f
parent633fef6dec9f078d7c02b737a76f3aad0ba5ccc8 (diff)
Enable refinements at Object#respond_to?
[Feature #15327] [Fix GH-2020] From: osyo-manga <manga.osyo@gmail.com> git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65920 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--NEWS2
-rw-r--r--spec/ruby/core/module/refine_spec.rb43
-rw-r--r--test/ruby/test_refinement.rb4
-rw-r--r--vm_method.c9
4 files changed, 44 insertions, 14 deletions
diff --git a/NEWS b/NEWS
index 24bd484cc2..b7a4e8018c 100644
--- a/NEWS
+++ b/NEWS
@@ -20,6 +20,8 @@ sufficient information, see the ChangeLog file or Redmine
* refinements takes place at Kernel#public_send. [Feature #15326]
+* refinements takes place at Kernel#respond_to?. [Feature #15327]
+
* +else+ without +rescue+ now causes a syntax error. [EXPERIMENTAL]
* constant names may start with a non-ASCII capital letter. [Feature #13770]
diff --git a/spec/ruby/core/module/refine_spec.rb b/spec/ruby/core/module/refine_spec.rb
index 97645e5466..3fa493b1da 100644
--- a/spec/ruby/core/module/refine_spec.rb
+++ b/spec/ruby/core/module/refine_spec.rb
@@ -524,21 +524,42 @@ describe "Module#refine" do
}.should raise_error(NameError, /undefined method `foo'/)
end
- it "is not honored by Kernel#respond_to?" do
- klass = Class.new
- refinement = Module.new do
- refine klass do
- def foo; end
+ ruby_version_is "" ... "2.6" do
+ it "is not honored by Kernel#respond_to?" do
+ klass = Class.new
+ refinement = Module.new do
+ refine klass do
+ def foo; end
+ end
end
- end
- result = nil
- Module.new do
- using refinement
- result = klass.new.respond_to?(:foo)
+ result = nil
+ Module.new do
+ using refinement
+ result = klass.new.respond_to?(:foo)
+ end
+
+ result.should == false
end
+ end
+
+ ruby_version_is "2.6" do
+ it "is honored by Kernel#respond_to?" do
+ klass = Class.new
+ refinement = Module.new do
+ refine klass do
+ def foo; end
+ end
+ end
- result.should == false
+ result = nil
+ Module.new do
+ using refinement
+ result = klass.new.respond_to?(:foo)
+ end
+
+ result.should == true
+ end
end
end
diff --git a/test/ruby/test_refinement.rb b/test/ruby/test_refinement.rb
index 11eea720bd..06150d998f 100644
--- a/test/ruby/test_refinement.rb
+++ b/test/ruby/test_refinement.rb
@@ -326,9 +326,9 @@ class TestRefinement < Test::Unit::TestCase
end
end
- def test_respond_to_should_not_use_refinements
+ def test_respond_to_should_use_refinements
assert_equal(false, 1.respond_to?(:foo))
- assert_equal(false, eval_using(IntegerFooExt, "1.respond_to?(:foo)"))
+ assert_equal(true, eval_using(IntegerFooExt, "1.respond_to?(:foo)"))
end
module StringCmpExt
diff --git a/vm_method.c b/vm_method.c
index c4f41bc118..0aeac2869e 100644
--- a/vm_method.c
+++ b/vm_method.c
@@ -1089,7 +1089,14 @@ 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, NULL);
+ const rb_method_entry_t *me;
+
+ if (ex & BOUND_RESPONDS) {
+ me = method_entry_resolve_refinement(klass, id, TRUE, NULL);
+ }
+ else {
+ me = rb_method_entry_without_refinements(klass, id, NULL);
+ }
if (me != 0) {
if ((ex & ~BOUND_RESPONDS) &&