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/