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

ruby-changes:45167

From: nobu <ko1@a...>
Date: Sat, 31 Dec 2016 17:08:05 +0900 (JST)
Subject: [ruby-changes:45167] nobu:r57240 (trunk): vm.c: fix return in lambda

nobu	2016-12-31 17:07:58 +0900 (Sat, 31 Dec 2016)

  New Revision: 57240

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

  Log:
    vm.c: fix return in lambda
    
    * vm.c (invoke_block_from_c_splattable): pass lambda-ness.
    
    * vm_eval.c (yield_under): invoke lambda proc properly.
      [ruby-core:78917] [Bug #13090]

  Modified files:
    trunk/test/ruby/test_lambda.rb
    trunk/vm.c
    trunk/vm_eval.c
Index: vm_eval.c
===================================================================
--- vm_eval.c	(revision 57239)
+++ vm_eval.c	(revision 57240)
@@ -16,7 +16,7 @@ struct local_var_list { https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L16
 };
 
 static inline VALUE method_missing(VALUE obj, ID id, int argc, const VALUE *argv, enum method_missing_reason call_status);
-static inline VALUE vm_yield_with_cref(rb_thread_t *th, int argc, const VALUE *argv, const rb_cref_t *cref);
+static inline VALUE vm_yield_with_cref(rb_thread_t *th, int argc, const VALUE *argv, const rb_cref_t *cref, int is_lambda);
 static inline VALUE vm_yield(rb_thread_t *th, int argc, const VALUE *argv);
 static inline VALUE vm_yield_with_block(rb_thread_t *th, int argc, const VALUE *argv, VALUE block_handler);
 static VALUE vm_exec(rb_thread_t *th);
@@ -1573,6 +1573,7 @@ yield_under(VALUE under, VALUE self, int https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L1573
     struct rb_captured_block new_captured;
     const VALUE *ep = NULL;
     rb_cref_t *cref;
+    int is_lambda = FALSE;
 
     if (block_handler != VM_BLOCK_HANDLER_NONE) {
       again:
@@ -1588,6 +1589,7 @@ yield_under(VALUE under, VALUE self, int https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L1589
 	    new_block_handler = VM_BH_FROM_IFUNC_BLOCK(&new_captured);
 	    break;
 	  case block_handler_type_proc:
+	    is_lambda = rb_proc_lambda_p(block_handler) != Qfalse;
 	    block_handler = vm_proc_to_block_handler(VM_BH_TO_PROC(block_handler));
 	    goto again;
 	  case block_handler_type_symbol:
@@ -1602,7 +1604,7 @@ yield_under(VALUE under, VALUE self, int https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L1604
     }
 
     cref = vm_cref_push(th, under, ep, TRUE);
-    return vm_yield_with_cref(th, argc, argv, cref);
+    return vm_yield_with_cref(th, argc, argv, cref, is_lambda);
 }
 
 VALUE
@@ -1623,7 +1625,7 @@ rb_yield_refine_block(VALUE refinement, https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L1625
 	CREF_REFINEMENTS_SET(cref, refinements);
 	VM_FORCE_WRITE_SPECIAL_CONST(&VM_CF_LEP(th->cfp)[VM_ENV_DATA_INDEX_SPECVAL], new_block_handler);
 	new_captured.self = refinement;
-	return vm_yield_with_cref(th, 0, NULL, cref);
+	return vm_yield_with_cref(th, 0, NULL, cref, FALSE);
     }
 }
 
Index: vm.c
===================================================================
--- vm.c	(revision 57239)
+++ vm.c	(revision 57240)
@@ -1021,9 +1021,9 @@ invoke_iseq_block_from_c(rb_thread_t *th https://github.com/ruby/ruby/blob/trunk/vm.c#L1021
 static inline VALUE
 invoke_block_from_c_splattable(rb_thread_t *th, VALUE block_handler,
 			       int argc, const VALUE *argv,
-			       VALUE passed_block_handler, const rb_cref_t *cref)
+			       VALUE passed_block_handler, const rb_cref_t *cref,
+			       int is_lambda)
 {
-    int is_lambda = FALSE;
   again:
     switch (vm_block_handler_type(block_handler)) {
       case block_handler_type_iseq:
@@ -1058,21 +1058,21 @@ check_block_handler(rb_thread_t *th) https://github.com/ruby/ruby/blob/trunk/vm.c#L1058
 }
 
 static VALUE
-vm_yield_with_cref(rb_thread_t *th, int argc, const VALUE *argv, const rb_cref_t *cref)
+vm_yield_with_cref(rb_thread_t *th, int argc, const VALUE *argv, const rb_cref_t *cref, int is_lambda)
 {
-    return invoke_block_from_c_splattable(th, check_block_handler(th), argc, argv, VM_BLOCK_HANDLER_NONE, cref);
+    return invoke_block_from_c_splattable(th, check_block_handler(th), argc, argv, VM_BLOCK_HANDLER_NONE, cref, is_lambda);
 }
 
 static VALUE
 vm_yield(rb_thread_t *th, int argc, const VALUE *argv)
 {
-    return invoke_block_from_c_splattable(th, check_block_handler(th), argc, argv, VM_BLOCK_HANDLER_NONE, NULL);
+    return invoke_block_from_c_splattable(th, check_block_handler(th), argc, argv, VM_BLOCK_HANDLER_NONE, NULL, FALSE);
 }
 
 static VALUE
 vm_yield_with_block(rb_thread_t *th, int argc, const VALUE *argv, VALUE block_handler)
 {
-    return invoke_block_from_c_splattable(th, check_block_handler(th), argc, argv, block_handler, NULL);
+    return invoke_block_from_c_splattable(th, check_block_handler(th), argc, argv, block_handler, NULL, FALSE);
 }
 
 static inline VALUE
Index: test/ruby/test_lambda.rb
===================================================================
--- test/ruby/test_lambda.rb	(revision 57239)
+++ test/ruby/test_lambda.rb	(revision 57240)
@@ -79,6 +79,26 @@ class TestLambdaParameters < Test::Unit: https://github.com/ruby/ruby/blob/trunk/test/ruby/test_lambda.rb#L79
     end
   end
 
+  def test_instance_eval_return
+    bug13090 = '[ruby-core:78917] [Bug #13090] cannot return in lambdas'
+    x = :ng
+    assert_nothing_raised(LocalJumpError) do
+      x = instance_eval(&->(_){return :ok})
+    end
+  ensure
+    assert_equal(:ok, x, bug13090)
+  end
+
+  def test_instance_exec_return
+    bug13090 = '[ruby-core:78917] [Bug #13090] cannot return in lambdas'
+    x = :ng
+    assert_nothing_raised(LocalJumpError) do
+      x = instance_exec(&->(){return :ok})
+    end
+  ensure
+    assert_equal(:ok, x, bug13090)
+  end
+
   def yield_1(arg)
     yield arg
   end

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

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