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

ruby-changes:64089

From: Koichi <ko1@a...>
Date: Fri, 11 Dec 2020 11:57:59 +0900 (JST)
Subject: [ruby-changes:64089] b53ccb9c69 (master): show deprecation warning correctly for lambda(&b)

https://git.ruby-lang.org/ruby.git/commit/?id=b53ccb9c69

From b53ccb9c69abd24e3bdad66cbe4c7e7480eaef16 Mon Sep 17 00:00:00 2001
From: Koichi Sasada <ko1@a...>
Date: Fri, 11 Dec 2020 11:54:50 +0900
Subject: show deprecation warning correctly for lambda(&b)

lambda(&b) where b is given block of method (like: def foo(&b))
should warn correctly.
[Feature #17361]

Also labmda(&labmda_block) or lambda(&:to_s) (Symbol#to_proc)
should not warn (but I'm not sure who cares about it).

diff --git a/proc.c b/proc.c
index ca70eb1..7e1985c 100644
--- a/proc.c
+++ b/proc.c
@@ -858,15 +858,23 @@ rb_block_lambda(void) https://github.com/ruby/ruby/blob/trunk/proc.c#L858
 static VALUE
 f_lambda(VALUE _)
 {
-    VALUE block_handler = rb_vm_frame_block_handler(GET_EC()->cfp);
+    rb_control_frame_t *cfp = GET_EC()->cfp;
+    VALUE block_handler = rb_vm_frame_block_handler(cfp);
 
     if (block_handler != VM_BLOCK_HANDLER_NONE) {
         switch (vm_block_handler_type(block_handler)) {
-          case block_handler_type_proc:
+          case block_handler_type_iseq:
+            if (RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)->ep == VM_BH_TO_ISEQ_BLOCK(block_handler)->ep) {
+                break;
+            }
           case block_handler_type_symbol:
+            break;
+          case block_handler_type_proc:
+            if (rb_proc_lambda_p(VM_BH_TO_PROC(block_handler))) {
+                break;
+            }
           case block_handler_type_ifunc:
             rb_warn_deprecated("lambda without a literal block", "the proc without lambda");
-          default:
             break;
         }
     }
diff --git a/test/ruby/test_proc.rb b/test/ruby/test_proc.rb
index c1f17a0..ca690dc 100644
--- a/test/ruby/test_proc.rb
+++ b/test/ruby/test_proc.rb
@@ -291,6 +291,45 @@ class TestProc < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_proc.rb#L291
     assert_equal(true, Proc.new(&l).lambda?)
   end
 
+  def self.helper_test_warn_lamda_with_passed_block &b
+    lambda(&b)
+  end
+
+  def self.def_lambda_warning name, warn
+    define_method(name, proc do
+      prev = Warning[:deprecated]
+      assert_warn warn do
+        Warning[:deprecated] = true
+        yield
+      end
+    ensure
+      Warning[:deprecated] = prev
+    end)
+  end
+
+  def_lambda_warning 'test_lambda_warning_normal', '' do
+    lambda{}
+  end
+
+  def_lambda_warning 'test_lambda_warning_pass_lambda', '' do
+    b = lambda{}
+    lambda(&b)
+  end
+
+  def_lambda_warning 'test_lambda_warning_pass_proc', /deprecated/ do
+    b = proc{}
+    lambda(&b)
+  end
+
+  def_lambda_warning 'test_lambda_warning_pass_proc', /deprecated/ do
+    helper_test_warn_lamda_with_passed_block{}
+  end
+
+  def_lambda_warning 'test_lambda_warning_pass_proc', '' do
+    # Symbol#to_proc returns lambda
+    helper_test_warn_lamda_with_passed_block(&:to_s)
+  end
+
   def test_curry_ski_fib
     s = proc {|f, g, x| f[x][g[x]] }.curry
     k = proc {|x, y| x }.curry
-- 
cgit v0.10.2


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

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