summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Thacker-Smith <Dylan.Smith@shopify.com>2019-07-02 15:06:54 +0100
committerNobuyoshi Nakada <nobu@ruby-lang.org>2019-09-20 02:20:59 +0900
commit7fbd2f7cc247ee66e877ab3c88f0274834c6b6c7 (patch)
tree1d03cfc0cba9aabb542306f7f1f685dfb636f0c1
parent17a13663998a98ff75fcc838d1cea95c879fbb88 (diff)
Allow calling a private method with `self.`
This makes it consistent with calling private attribute assignment methods, which currently is allowed (e.g. `self.value =`). Calling a private method in this way can be useful when trying to assign the return value to a local variable with the same name. [Feature #11297] [Feature #16123]
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/2474
-rw-r--r--compile.c4
-rw-r--r--spec/ruby/language/send_spec.rb2
-rw-r--r--test/ruby/test_method.rb2
-rw-r--r--test/ruby/test_module.rb3
-rw-r--r--test/ruby/test_refinement.rb2
5 files changed, 9 insertions, 4 deletions
diff --git a/compile.c b/compile.c
index 7cfda23f18..cea09c8f8a 100644
--- a/compile.c
+++ b/compile.c
@@ -6773,6 +6773,10 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
iseq_block_param_id_p(iseq, node->nd_recv->nd_vid, &idx, &level)) {
ADD_INSN2(recv, nd_line(node->nd_recv), getblockparamproxy, INT2FIX(idx + VM_ENV_DATA_SIZE - 1), INT2FIX(level));
}
+ else if (private_recv_p(node)) {
+ ADD_INSN(recv, nd_line(node), putself);
+ flag |= VM_CALL_FCALL;
+ }
else {
CHECK(COMPILE(recv, "recv", node->nd_recv));
}
diff --git a/spec/ruby/language/send_spec.rb b/spec/ruby/language/send_spec.rb
index 4ba3dcc9c2..cce2e1acb9 100644
--- a/spec/ruby/language/send_spec.rb
+++ b/spec/ruby/language/send_spec.rb
@@ -260,7 +260,7 @@ end
describe "Invoking a private getter method" do
it "does not permit self as a receiver" do
receiver = LangSendSpecs::PrivateGetter.new
- -> { receiver.call_self_foo }.should raise_error(NoMethodError)
+ -> { receiver.call_self_foo }.should_not raise_error(NoMethodError)
-> { receiver.call_self_foo_or_equals(6) }.should raise_error(NoMethodError)
end
end
diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb
index 1289b44c63..a8064c47c2 100644
--- a/test/ruby/test_method.rb
+++ b/test/ruby/test_method.rb
@@ -673,7 +673,7 @@ class TestMethod < Test::Unit::TestCase
assert_nothing_raised { mv3 }
assert_nothing_raised { self.mv1 }
- assert_raise(NoMethodError) { self.mv2 }
+ assert_nothing_raised { self.mv2 }
assert_nothing_raised { self.mv3 }
v = Visibility.new
diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb
index 7bb2261ffb..8689c60dcd 100644
--- a/test/ruby/test_module.rb
+++ b/test/ruby/test_module.rb
@@ -2479,7 +2479,8 @@ class TestModule < Test::Unit::TestCase
assert_include(methods, :#{method}, ":#{method} should be private")
assert_raise_with_message(NoMethodError, "private method `#{method}' called for main:Object") {
- self.#{method}
+ recv = self
+ recv.#{method}
}
}
end
diff --git a/test/ruby/test_refinement.rb b/test/ruby/test_refinement.rb
index 87d60e41a4..4be0720983 100644
--- a/test/ruby/test_refinement.rb
+++ b/test/ruby/test_refinement.rb
@@ -538,7 +538,7 @@ class TestRefinement < Test::Unit::TestCase
def test_main_using_is_private
assert_raise(NoMethodError) do
- eval("self.using Module.new", Sandbox::BINDING)
+ eval("recv = self; recv.using Module.new", Sandbox::BINDING)
end
end