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

ruby-changes:69518

From: Nobuyoshi <ko1@a...>
Date: Fri, 29 Oct 2021 18:54:10 +0900 (JST)
Subject: [ruby-changes:69518] ec2e04c90d (master): Preserve the encoding of message from outer local variables

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

From ec2e04c90d96541502c9b96e66900b4bb01676bb Mon Sep 17 00:00:00 2001
From: Nobuyoshi Nakada <nobu@r...>
Date: Fri, 29 Oct 2021 17:34:09 +0900
Subject: Preserve the encoding of message from outer local variables

---
 test/ruby/test_iseq.rb |  8 ++++++
 test/ruby/test_proc.rb |  6 ++++
 vm.c                   | 74 ++++++++++++++++++--------------------------------
 3 files changed, 41 insertions(+), 47 deletions(-)

diff --git a/test/ruby/test_iseq.rb b/test/ruby/test_iseq.rb
index 7125a5ac6d8..af92edc4942 100644
--- a/test/ruby/test_iseq.rb
+++ b/test/ruby/test_iseq.rb
@@ -105,6 +105,14 @@ class TestISeq < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_iseq.rb#L105
     assert_equal(42, ISeq.load_from_binary(iseq.to_binary).eval)
   end
 
+  def test_ractor_unshareable_outer_variable
+    name = "\u{2603 26a1}"
+    y = eval("proc {#{name} = nil; proc {|x| #{name} = x}}").call
+    assert_raise_with_message(ArgumentError, /\(#{name}\)/) do
+      Ractor.make_shareable(y)
+    end
+  end
+
   def test_disasm_encoding
     src = "\u{3042} = 1; \u{3042}; \u{3043}"
     asm = compile(src).disasm
diff --git a/test/ruby/test_proc.rb b/test/ruby/test_proc.rb
index 1f87085f9fa..51872e49beb 100644
--- a/test/ruby/test_proc.rb
+++ b/test/ruby/test_proc.rb
@@ -1611,6 +1611,12 @@ class TestProc < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_proc.rb#L1611
       Proc.new{yield}.isolate
     end
 
+
+    name = "\u{2603 26a1}"
+    assert_raise_with_message(ArgumentError, /\(#{name}\)/) do
+      eval("#{name} = :#{name}; Proc.new {p #{name}}").isolate
+    end
+
     # binding
 
     :a.tap{|a|
diff --git a/vm.c b/vm.c
index 7f3376ce689..18725de5a4a 100644
--- a/vm.c
+++ b/vm.c
@@ -1074,6 +1074,30 @@ proc_isolate_env(VALUE self, rb_proc_t *proc, VALUE read_only_variables) https://github.com/ruby/ruby/blob/trunk/vm.c#L1074
     RB_OBJ_WRITTEN(self, Qundef, env);
 }
 
+static VALUE
+proc_shared_outer_variables(struct rb_id_table *outer_variables, bool isolate, const char *message)
+{
+    struct collect_outer_variable_name_data data = {
+        .isolate = isolate,
+        .ary = Qfalse,
+        .read_only = Qfalse,
+        .yield = false,
+    };
+    rb_id_table_foreach(outer_variables, collect_outer_variable_names, (void *)&data);
+
+    if (data.ary != Qfalse) {
+        VALUE str = rb_sprintf("can not %s because it accesses outer variables (%"PRIsVALUE")", message,
+                               rb_ary_join(data.ary, rb_str_new2(", ")));
+        rb_str_cat_cstr(str, data.yield ? " and uses `yield'." : ".");
+        rb_exc_raise(rb_exc_new_str(rb_eArgError, str));
+    }
+    else if (data.yield) {
+        rb_raise(rb_eArgError, "can not %s because it uses `yield'.", message);
+    }
+
+    return data.read_only;
+}
+
 VALUE
 rb_proc_isolate_bang(VALUE self)
 {
@@ -1084,28 +1108,7 @@ rb_proc_isolate_bang(VALUE self) https://github.com/ruby/ruby/blob/trunk/vm.c#L1108
         if (proc->block.type != block_type_iseq) rb_raise(rb_eRuntimeError, "not supported yet");
 
         if (iseq->body->outer_variables) {
-            struct collect_outer_variable_name_data data = {
-                .isolate = true,
-                .ary = Qfalse,
-                .yield = false,
-            };
-            rb_id_table_foreach(iseq->body->outer_variables, collect_outer_variable_names, (void *)&data);
-
-            if (data.ary != Qfalse) {
-                VALUE str = rb_ary_join(data.ary, rb_str_new2(", "));
-                if (data.yield) {
-                    rb_raise(rb_eArgError, "can not isolate a Proc because it accesses outer variables (%s) and uses `yield'.",
-                             StringValueCStr(str));
-                }
-                else {
-                    rb_raise(rb_eArgError, "can not isolate a Proc because it accesses outer variables (%s).",
-                             StringValueCStr(str));
-                }
-            }
-            else {
-                VM_ASSERT(data.yield);
-                rb_raise(rb_eArgError, "can not isolate a Proc because it uses `yield'.");
-            }
+            proc_shared_outer_variables(iseq->body->outer_variables, true, "isolate a Proc");
         }
 
         proc_isolate_env(self, proc, Qfalse);
@@ -1136,31 +1139,8 @@ rb_proc_ractor_make_shareable(VALUE self) https://github.com/ruby/ruby/blob/trunk/vm.c#L1139
         VALUE read_only_variables = Qfalse;
 
         if (iseq->body->outer_variables) {
-            struct collect_outer_variable_name_data data = {
-                .isolate = false,
-                .ary = Qfalse,
-                .read_only = Qfalse,
-                .yield = false,
-            };
-
-            rb_id_table_foreach(iseq->body->outer_variables, collect_outer_variable_names, (void *)&data);
-
-            if (data.ary != Qfalse) {
-                VALUE str = rb_ary_join(data.ary, rb_str_new2(", "));
-                if (data.yield) {
-                    rb_raise(rb_eArgError, "can not make a Proc shareable because it accesses outer variables (%s) and uses `yield'.",
-                             StringValueCStr(str));
-                }
-                else {
-                    rb_raise(rb_eArgError, "can not make a Proc shareable because it accesses outer variables (%s).",
-                             StringValueCStr(str));
-                }
-            }
-            else if (data.yield) {
-                rb_raise(rb_eArgError, "can not make a Proc shareable because it uses `yield'.");
-            }
-
-            read_only_variables = data.read_only;
+            read_only_variables =
+                proc_shared_outer_variables(iseq->body->outer_variables, false, "make a Proc shareable");
         }
 
         proc_isolate_env(self, proc, read_only_variables);
-- 
cgit v1.2.1


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

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