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/