summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--NEWS5
-rw-r--r--test/ruby/test_lambda.rb20
-rw-r--r--vm_insnhelper.c7
4 files changed, 37 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 46015299f2..c214f213ef 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Fri Aug 9 10:42:11 2013 Kazuki Tsujimoto <kazuki@callcc.net>
+
+ * vm_insnhelper.c (vm_invoke_block): returning from lambda proc
+ now always exits from the Proc. [ruby-core:56193] [Feature #8693]
+
+ * NEWS, test/ruby/test_lambda.rb: ditto. Patch by nobu.
+
Fri Aug 9 00:10:32 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
* enumerator.c (lazy_zip_func): fix non-single argument. fix
diff --git a/NEWS b/NEWS
index cd7cad8436..f27a26f25b 100644
--- a/NEWS
+++ b/NEWS
@@ -97,6 +97,11 @@ with all sufficient information, see the ChangeLog file.
* Raises TypeError instead of ArgumentError if the receiver doesn't have
to_r method.
+* Proc
+ * Returning from lambda proc now always exits from the Proc, not from the
+ method where the lambda is created. Returing from non-lambda proc exits
+ from the method, same as the former behavior.
+
=== Stdlib updates (outstanding ones only)
* Digest
diff --git a/test/ruby/test_lambda.rb b/test/ruby/test_lambda.rb
index 40bd134e2f..f042ab015e 100644
--- a/test/ruby/test_lambda.rb
+++ b/test/ruby/test_lambda.rb
@@ -89,4 +89,24 @@ class TestLambdaParameters < Test::Unit::TestCase
assert_send([e.backtrace.first, :start_with?, "#{__FILE__}:#{line}:"], bug6151)
assert_equal(0, called)
end
+
+ def return_in_current(val)
+ 1.tap &->(*) {return 0}
+ val
+ end
+
+ def yield_block
+ yield
+ end
+
+ def return_in_callee(val)
+ yield_block &->(*) {return 0}
+ val
+ end
+
+ def test_return
+ feature8693 = '[ruby-core:56193] [Feature #8693]'
+ assert_equal(42, return_in_current(42), feature8693)
+ assert_equal(42, return_in_callee(42), feature8693)
+ end
end
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 1d0b225dbd..c3a243f815 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -2328,12 +2328,15 @@ vm_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_info_t *ci
if (BUILTIN_TYPE(iseq) != T_NODE) {
int opt_pc;
const int arg_size = iseq->arg_size;
+ int is_lambda = block_proc_is_lambda(block->proc);
VALUE * const rsp = GET_SP() - ci->argc;
SET_SP(rsp);
- opt_pc = vm_yield_setup_args(th, iseq, ci->argc, rsp, 0, block_proc_is_lambda(block->proc));
+ opt_pc = vm_yield_setup_args(th, iseq, ci->argc, rsp, 0, is_lambda);
- vm_push_frame(th, iseq, VM_FRAME_MAGIC_BLOCK, block->self,
+ vm_push_frame(th, iseq,
+ is_lambda ? VM_FRAME_MAGIC_LAMBDA : VM_FRAME_MAGIC_BLOCK,
+ block->self,
block->klass,
VM_ENVVAL_PREV_EP_PTR(block->ep),
iseq->iseq_encoded + opt_pc,