ruby-changes:69811
From: Jeremy <ko1@a...>
Date: Fri, 19 Nov 2021 02:48:01 +0900 (JST)
Subject: [ruby-changes:69811] 75ecbda438 (master): Make Module#{public, private, protected, module_function} return arguments
https://git.ruby-lang.org/ruby.git/commit/?id=75ecbda438 From 75ecbda438670ec12641d1324d0e81a52ee02e0a Mon Sep 17 00:00:00 2001 From: Jeremy Evans <code@j...> Date: Wed, 27 Oct 2021 10:35:54 -0700 Subject: Make Module#{public,private,protected,module_function} return arguments Previously, each of these methods returned self, but it is more useful to return arguments, to allow for simpler method decorators, such as: ```ruby cached private def foo; some_long_calculation; end ``` Where cached sets up caching for the method. For each of these methods, the following behavior is used: 1) No arguments returns nil 2) Single argument is returned 3) Multiple arguments are returned as an array The single argument case is really the case we are trying to optimize for, for the same reason that def was changed to return a symbol for the method. Idea and initial patch from Herwin Quarantainenet. Implements [Feature #12495] --- spec/ruby/core/main/private_spec.rb | 12 ++++++-- spec/ruby/core/main/public_spec.rb | 13 +++++++-- spec/ruby/core/module/module_function_spec.rb | 40 +++++++++++++++++++-------- spec/ruby/core/module/private_spec.rb | 24 ++++++++++++---- spec/ruby/core/module/protected_spec.rb | 24 ++++++++++++---- spec/ruby/core/module/public_spec.rb | 25 +++++++++++++---- test/ruby/test_module.rb | 22 +++++++++++++++ vm_method.c | 16 +++++++---- 8 files changed, 139 insertions(+), 37 deletions(-) diff --git a/spec/ruby/core/main/private_spec.rb b/spec/ruby/core/main/private_spec.rb index 78c5d287d4d..cac0645b404 100644 --- a/spec/ruby/core/main/private_spec.rb +++ b/spec/ruby/core/main/private_spec.rb @@ -32,8 +32,16 @@ describe "main#private" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/main/private_spec.rb#L32 end end - it "returns Object" do - eval("private :main_public_method", TOPLEVEL_BINDING).should equal(Object) + ruby_version_is ''...'3.1' do + it "returns Object" do + eval("private :main_public_method", TOPLEVEL_BINDING).should equal(Object) + end + end + + ruby_version_is '3.1' do + it "returns argument" do + eval("private :main_public_method", TOPLEVEL_BINDING).should equal(:main_public_method) + end end it "raises a NameError when at least one of given method names is undefined" do diff --git a/spec/ruby/core/main/public_spec.rb b/spec/ruby/core/main/public_spec.rb index bfc27a9e804..91f045dbab1 100644 --- a/spec/ruby/core/main/public_spec.rb +++ b/spec/ruby/core/main/public_spec.rb @@ -32,10 +32,19 @@ describe "main#public" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/main/public_spec.rb#L32 end end - it "returns Object" do - eval("public :main_private_method", TOPLEVEL_BINDING).should equal(Object) + ruby_version_is ''...'3.1' do + it "returns Object" do + eval("public :main_private_method", TOPLEVEL_BINDING).should equal(Object) + end end + ruby_version_is '3.1' do + it "returns argument" do + eval("public :main_private_method", TOPLEVEL_BINDING).should equal(:main_private_method) + end + end + + it "raises a NameError when given an undefined name" do -> do eval "public :main_undefined_method", TOPLEVEL_BINDING diff --git a/spec/ruby/core/module/module_function_spec.rb b/spec/ruby/core/module/module_function_spec.rb index 407237d48fb..0602e95ca9c 100644 --- a/spec/ruby/core/module/module_function_spec.rb +++ b/spec/ruby/core/module/module_function_spec.rb @@ -38,14 +38,23 @@ describe "Module#module_function with specific method names" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/module/module_function_spec.rb#L38 m.respond_to?(:test3).should == false end - it "returns the current module" do - x = nil - m = Module.new do - def test() end - x = module_function :test + ruby_version_is ""..."3.1" do + it "returns self" do + Module.new do + def foo; end + module_function(:foo).should equal(self) + end end + end - x.should == m + ruby_version_is "3.1" do + it "returns argument or arguments if given" do + Module.new do + def foo; end + module_function(:foo).should equal(:foo) + module_function(:foo, :foo).should == [:foo, :foo] + end + end end it "creates an independent copy of the method, not a redirect" do @@ -160,13 +169,20 @@ describe "Module#module_function as a toggle (no arguments) in a Module body" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/module/module_function_spec.rb#L169 m.respond_to?(:test2).should == true end - it "returns the current module" do - x = nil - m = Module.new { - x = module_function - } + ruby_version_is ""..."3.1" do + it "returns self" do + Module.new do + module_function.should equal(self) + end + end + end - x.should == m + ruby_version_is "3.1" do + it "returns nil" do + Module.new do + module_function.should equal(nil) + end + end end it "stops creating module functions if the body encounters another toggle " \ diff --git a/spec/ruby/core/module/private_spec.rb b/spec/ruby/core/module/private_spec.rb index e893c24f38b..ead806637c9 100644 --- a/spec/ruby/core/module/private_spec.rb +++ b/spec/ruby/core/module/private_spec.rb @@ -38,11 +38,25 @@ describe "Module#private" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/module/private_spec.rb#L38 :module_specs_public_method_on_object_for_kernel_private) end - it "returns self" do - (class << Object.new; self; end).class_eval do - def foo; end - private(:foo).should equal(self) - private.should equal(self) + ruby_version_is ""..."3.1" do + it "returns self" do + (class << Object.new; self; end).class_eval do + def foo; end + private(:foo).should equal(self) + private.should equal(self) + end + end + end + + ruby_version_is "3.1" do + it "returns argument or arguments if given" do + (class << Object.new; self; end).class_eval do + def foo; end + private(:foo).should equal(:foo) + private([:foo, :foo]).should == [:foo, :foo] + private(:foo, :foo).should == [:foo, :foo] + private.should equal(nil) + end end end diff --git a/spec/ruby/core/module/protected_spec.rb b/spec/ruby/core/module/protected_spec.rb index aa04a42fb8e..058d49d751e 100644 --- a/spec/ruby/core/module/protected_spec.rb +++ b/spec/ruby/core/module/protected_spec.rb @@ -39,11 +39,25 @@ describe "Module#protected" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/module/protected_spec.rb#L39 :module_specs_public_method_on_object_for_kernel_protected) end - it "returns self" do - (class << Object.new; self; end).class_eval do - def foo; end - protected(:foo).should equal(self) - protected.should equal(self) + ruby_version_is ""..."3.1" do + it "returns self" do + (class << Object.new; self; end).class_eval do + def foo; end + protected(:foo).should equal(self) + protected.should equal(self) + end + end + end + + ruby_version_is "3.1" do + it "returns argument or arguments if given" do + (class << Object.new; self; end).class_eval do + def foo; end + protected(:foo).should equal(:foo) + protected([:foo, :foo]).should == [:foo, :foo] + protected(:foo, :foo).should == [:foo, :foo] + protected.should equal(nil) + end end end diff --git a/spec/ruby/core/module/public_spec.rb b/spec/ruby/core/module/public_spec.rb index e7059f6aa63..e3b183f228a 100644 --- a/spec/ruby/core/module/public_spec.rb +++ b/spec/ruby/core/module/public_spec.rb @@ -27,12 +27,25 @@ describe "Module#public" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/module/public_spec.rb#L27 :module_specs_private_method_on_object_for_kernel_public) end - it "returns self" do - (class << Object.new; self; end).class_eval do - def foo; end - private :foo - public(:foo).should equal(self) - public.should equal(self) + ruby_version_is ""..."3.1" do + it "returns self" do + (class << Object.new; self; end).class_eval do + def foo; end + public(:foo).should equal(self) + public.should equal(self) + end + end + end + + ruby_version_is "3.1" do + it "returns argument or arguments if given" do + (class << Object.new; self; end).class_eval do + def foo; end + public(:foo).should equal(:foo) + public([:foo, :foo]).should == [:foo, :foo] + public(:foo, :foo).should == [:foo, :foo] + public.should equal(nil) + end end end diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb index be23b84c462..e1524a5d815 100644 --- a/test/ruby/test_module.rb +++ b/test/ruby/test_module.rb @@ -1014,6 +1014,28 @@ class TestModule < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_module.rb#L1014 assert_raise(NoMethodError, /protected method/) {o.aClass2} end + def test_visibility_method_return_value + no_arg_results = nil + c = Module.new do + singleton_class.send(:public, :public, :private, :protected, :module_function) + def foo; end + def bar; end + no_arg_results = [public, private, protected, module_function] + end + + assert_equal([nil]*4, no_arg_results) + + assert_equal(:foo, c.private(:foo)) + assert_equal(:foo, c.public(:foo)) + assert_equal(:foo, c.protected(:foo)) + assert_equal(:foo, c.module_function(:foo)) + + assert_equal([:foo, :bar], c.private(:foo, :bar)) + assert_equal([:foo, :bar], c.public(:foo, :bar)) + assert_equal([:foo, :bar], c.protected(:foo, :bar)) + assert_equal([:foo, :bar], c.module_function(:foo, :bar)) + end + def test_s_constants (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/