summaryrefslogtreecommitdiff
path: root/proc.c
diff options
context:
space:
mode:
authorAlan Wu <XrXr@users.noreply.github.com>2023-09-07 14:56:07 -0400
committerAlan Wu <XrXr@users.noreply.github.com>2023-09-12 11:25:07 -0400
commit39ee3e22bd3d071c1c283b6b8dbd1af413342fb1 (patch)
treeda6a4f4c93d1887d477776b7f4575d5146f702e4 /proc.c
parentb90272b3b661bd2fd557332028b8feb568b6b9df (diff)
Make Kernel#lambda raise when given non-literal block
Previously, Kernel#lambda returned a non-lambda proc when given a non-literal block and issued a warning under the `:deprecated` category. With this change, Kernel#lambda will always return a lambda proc, if it returns without raising. Due to interactions with block passing optimizations, we previously had two separate code paths for detecting whether Kernel#lambda got a literal block. This change allows us to remove one path, the hack done with rb_control_frame_t::block_code introduced in 85a337f for supporting situations where Kernel#lambda returned a non-lambda proc. [Feature #19777] Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com>
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/8405
Diffstat (limited to 'proc.c')
-rw-r--r--proc.c49
1 files changed, 22 insertions, 27 deletions
diff --git a/proc.c b/proc.c
index 9fd24a8fd4..0f4735b589 100644
--- a/proc.c
+++ b/proc.c
@@ -793,16 +793,8 @@ proc_new(VALUE klass, int8_t is_lambda)
break;
case block_handler_type_ifunc:
- return rb_vm_make_proc_lambda(ec, VM_BH_TO_CAPT_BLOCK(block_handler), klass, is_lambda);
case block_handler_type_iseq:
- {
- const struct rb_captured_block *captured = VM_BH_TO_CAPT_BLOCK(block_handler);
- rb_control_frame_t *last_ruby_cfp = rb_vm_get_ruby_level_next_cfp(ec, cfp);
- if (is_lambda && last_ruby_cfp && vm_cfp_forwarded_bh_p(last_ruby_cfp, block_handler)) {
- is_lambda = false;
- }
- return rb_vm_make_proc_lambda(ec, captured, klass, is_lambda);
- }
+ return rb_vm_make_proc_lambda(ec, VM_BH_TO_CAPT_BLOCK(block_handler), klass, is_lambda);
}
VM_UNREACHABLE(proc_new);
return Qnil;
@@ -857,31 +849,34 @@ rb_block_lambda(void)
}
static void
-f_lambda_warn(void)
+f_lambda_filter_non_literal(void)
{
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_iseq:
- if (RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)->ep == VM_BH_TO_ISEQ_BLOCK(block_handler)->ep) {
- return;
- }
- break;
- case block_handler_type_symbol:
+ if (block_handler == VM_BLOCK_HANDLER_NONE) {
+ // no block erorr raised else where
+ return;
+ }
+
+ switch (vm_block_handler_type(block_handler)) {
+ case block_handler_type_iseq:
+ if (RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)->ep == VM_BH_TO_ISEQ_BLOCK(block_handler)->ep) {
return;
- case block_handler_type_proc:
- if (rb_proc_lambda_p(VM_BH_TO_PROC(block_handler))) {
- return;
- }
- break;
- case block_handler_type_ifunc:
- break;
}
+ break;
+ case block_handler_type_symbol:
+ return;
+ case block_handler_type_proc:
+ if (rb_proc_lambda_p(VM_BH_TO_PROC(block_handler))) {
+ return;
+ }
+ break;
+ case block_handler_type_ifunc:
+ break;
}
- rb_warn_deprecated("lambda without a literal block", "the proc without lambda");
+ rb_raise(rb_eArgError, "the lambda method requires a literal block");
}
/*
@@ -895,7 +890,7 @@ f_lambda_warn(void)
static VALUE
f_lambda(VALUE _)
{
- f_lambda_warn();
+ f_lambda_filter_non_literal();
return rb_block_lambda();
}