Skip to content

Commit

Permalink
Enable refinements at Object#respond_to?
Browse files Browse the repository at this point in the history
[Feature #15327] [Fix rubyGH-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
  • Loading branch information
nobu authored and Joe Truba committed Dec 10, 2018
1 parent 559b841 commit 1e53d22
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 14 deletions.
2 changes: 2 additions & 0 deletions NEWS
Expand Up @@ -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]
Expand Down
43 changes: 32 additions & 11 deletions spec/ruby/core/module/refine_spec.rb
Expand Up @@ -524,21 +524,42 @@ def foo; end
}.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

Expand Down
4 changes: 2 additions & 2 deletions test/ruby/test_refinement.rb
Expand Up @@ -326,9 +326,9 @@ def foo; "foo"; end
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
Expand Down
9 changes: 8 additions & 1 deletion vm_method.c
Expand Up @@ -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) &&
Expand Down

0 comments on commit 1e53d22

Please sign in to comment.