[前][次][番号順一覧][スレッド一覧]

ruby-changes:53703

From: nobu <ko1@a...>
Date: Thu, 22 Nov 2018 16:53:12 +0900 (JST)
Subject: [ruby-changes:53703] nobu:r65919 (trunk): Enable refinements to public_send.

nobu	2018-11-22 16:53:07 +0900 (Thu, 22 Nov 2018)

  New Revision: 65919

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=65919

  Log:
    Enable refinements to public_send.
    
    [Feature #15326] [Fix GH-2019]
    
    From: manga_osyo <manga.osyo@g...>

  Modified files:
    trunk/NEWS
    trunk/spec/ruby/core/module/refine_spec.rb
    trunk/test/ruby/test_refinement.rb
    trunk/vm_eval.c
Index: vm_eval.c
===================================================================
--- vm_eval.c	(revision 65918)
+++ vm_eval.c	(revision 65919)
@@ -290,8 +290,16 @@ rb_call0(rb_execution_context_t *ec, https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L290
 	 VALUE recv, ID mid, int argc, const VALUE *argv,
 	 call_type scope, VALUE self)
 {
-    const rb_callable_method_entry_t *me = rb_search_method_entry(recv, mid);
-    enum method_missing_reason call_status = rb_method_call_status(ec, me, scope, self);
+    const rb_callable_method_entry_t *me;
+    enum method_missing_reason call_status;
+
+    if (scope == CALL_PUBLIC) {
+        me = rb_callable_method_entry_with_refinements(CLASS_OF(recv), mid, NULL);
+    }
+    else {
+        me = rb_search_method_entry(recv, mid);
+    }
+    call_status = rb_method_call_status(ec, me, scope, self);
 
     if (call_status != MISSING_NONE) {
 	return method_missing(recv, mid, argc, argv, call_status);
Index: spec/ruby/core/module/refine_spec.rb
===================================================================
--- spec/ruby/core/module/refine_spec.rb	(revision 65918)
+++ spec/ruby/core/module/refine_spec.rb	(revision 65919)
@@ -425,6 +425,24 @@ describe "Module#refine" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/module/refine_spec.rb#L425
       end
     end
 
+    ruby_version_is "2.6" do
+      it "is honored by Kernel#public_send" do
+        refinement = Module.new do
+          refine ModuleSpecs::ClassWithFoo do
+            def foo; "foo from refinement"; end
+          end
+        end
+
+        result = nil
+        Module.new do
+          using refinement
+          result = ModuleSpecs::ClassWithFoo.new.public_send :foo
+        end
+
+        result.should == "foo from refinement"
+      end
+    end
+
     ruby_version_is "" ... "2.5" do
       it "is not honored by string interpolation" do
         refinement = Module.new do
Index: NEWS
===================================================================
--- NEWS	(revision 65918)
+++ NEWS	(revision 65919)
@@ -16,7 +16,9 @@ sufficient information, see the ChangeLo https://github.com/ruby/ruby/blob/trunk/NEWS#L16
 
 * <code>$SAFE</code> is a process global state and we can set 0 again. [Feature #14250]
 
-* refinements take place at block passing.  [Feature #14223]
+* refinements takes place at block passing.  [Feature #14223]
+
+* refinements takes place at Kernel#public_send.  [Feature #15326]
 
 * +else+ without +rescue+ now causes a syntax error.  [EXPERIMENTAL]
 
Index: test/ruby/test_refinement.rb
===================================================================
--- test/ruby/test_refinement.rb	(revision 65918)
+++ test/ruby/test_refinement.rb	(revision 65919)
@@ -19,6 +19,10 @@ class TestRefinement < Test::Unit::TestC https://github.com/ruby/ruby/blob/trunk/test/ruby/test_refinement.rb#L19
       return "Foo#a"
     end
 
+    def b
+      return "Foo#b"
+    end
+
     def call_x
       return x
     end
@@ -41,6 +45,10 @@ class TestRefinement < Test::Unit::TestC https://github.com/ruby/ruby/blob/trunk/test/ruby/test_refinement.rb#L45
       def a
         return "FooExt#a"
       end
+
+      private def b
+        return "FooExt#b"
+      end
     end
   end
 
@@ -94,6 +102,18 @@ class TestRefinement < Test::Unit::TestC https://github.com/ruby/ruby/blob/trunk/test/ruby/test_refinement.rb#L102
         return foo.send(:z)
       end
 
+      def self.send_b_on(foo)
+        return foo.send(:b)
+      end
+
+      def self.public_send_z_on(foo)
+        return foo.public_send(:z)
+      end
+
+      def self.public_send_b_on(foo)
+        return foo.public_send(:b)
+      end
+
       def self.method_z(foo)
         return foo.method(:z)
       end
@@ -179,11 +199,20 @@ class TestRefinement < Test::Unit::TestC https://github.com/ruby/ruby/blob/trunk/test/ruby/test_refinement.rb#L199
     foo = Foo.new
     assert_raise(NoMethodError) { foo.send(:z) }
     assert_equal("FooExt#z", FooExtClient.send_z_on(foo))
+    assert_equal("FooExt#b", FooExtClient.send_b_on(foo))
     assert_raise(NoMethodError) { foo.send(:z) }
 
     assert_equal(true, RespondTo::Sub.new.respond_to?(:foo))
   end
 
+  def test_public_send_should_use_refinements
+    foo = Foo.new
+    assert_raise(NoMethodError) { foo.public_send(:z) }
+    assert_equal("FooExt#z", FooExtClient.public_send_z_on(foo))
+    assert_equal("Foo#b", foo.public_send(:b))
+    assert_raise(NoMethodError) { FooExtClient.public_send_b_on(foo) }
+  end
+
   def test_method_should_not_use_refinements
     foo = Foo.new
     assert_raise(NameError) { foo.method(:z) }
@@ -907,6 +936,10 @@ class TestRefinement < Test::Unit::TestC https://github.com/ruby/ruby/blob/trunk/test/ruby/test_refinement.rb#L936
       return foo.send(:z)
     end
 
+    def self.public_send_z_on(foo)
+      return foo.public_send(:z)
+    end
+
     def self.method_z(foo)
       return foo.method(:z)
     end

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]