summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--internal/string.h1
-rw-r--r--io.c25
-rw-r--r--ruby.c4
-rwxr-xr-xspec/ruby/command_line/dash_0_spec.rb13
-rw-r--r--spec/ruby/language/predefined_spec.rb71
-rw-r--r--string.c8
6 files changed, 110 insertions, 12 deletions
diff --git a/internal/string.h b/internal/string.h
index 87cefa13d5..0ff92c3b84 100644
--- a/internal/string.h
+++ b/internal/string.h
@@ -61,6 +61,7 @@ size_t rb_str_size_as_embedded(VALUE);
bool rb_str_reembeddable_p(VALUE);
VALUE rb_str_upto_endless_each(VALUE, int (*each)(VALUE, VALUE), VALUE);
VALUE rb_str_with_debug_created_info(VALUE, VALUE, int);
+VALUE rb_str_frozen_bare_string(VALUE);
/* error.c */
void rb_warn_unchilled_literal(VALUE str);
diff --git a/io.c b/io.c
index 10f0f5f892..6504f97d5b 100644
--- a/io.c
+++ b/io.c
@@ -8673,6 +8673,25 @@ deprecated_str_setter(VALUE val, ID id, VALUE *var)
*var = val;
}
+static void
+deprecated_rs_setter(VALUE val, ID id, VALUE *var)
+{
+ if (!NIL_P(val)) {
+ if (!RB_TYPE_P(val, T_STRING)) {
+ rb_raise(rb_eTypeError, "value of %"PRIsVALUE" must be String", rb_id2str(id));
+ }
+ if (rb_str_equal(val, rb_default_rs)) {
+ val = rb_default_rs;
+ }
+ else {
+ val = rb_str_frozen_bare_string(val);
+ }
+ rb_enc_str_coderange(val);
+ rb_warn_deprecated("'%s'", NULL, rb_id2name(id));
+ }
+ *var = val;
+}
+
/*
* call-seq:
* print(*objects) -> nil
@@ -15713,8 +15732,10 @@ Init_IO(void)
rb_vm_register_global_object(rb_default_rs);
rb_rs = rb_default_rs;
rb_output_rs = Qnil;
- rb_define_hooked_variable("$/", &rb_rs, 0, deprecated_str_setter);
- rb_define_hooked_variable("$-0", &rb_rs, 0, deprecated_str_setter);
+ rb_define_hooked_variable("$/", &rb_rs, 0, deprecated_rs_setter);
+ rb_gvar_ractor_local("$/"); // not local but ractor safe
+ rb_define_hooked_variable("$-0", &rb_rs, 0, deprecated_rs_setter);
+ rb_gvar_ractor_local("$-0"); // not local but ractor safe
rb_define_hooked_variable("$\\", &rb_output_rs, 0, deprecated_str_setter);
rb_define_virtual_variable("$_", get_LAST_READ_LINE, set_LAST_READ_LINE);
diff --git a/ruby.c b/ruby.c
index 4dbd5909c8..49d6b3d091 100644
--- a/ruby.c
+++ b/ruby.c
@@ -1325,11 +1325,11 @@ proc_0_option(ruby_cmdline_options_t *opt, const char *s)
if (v > 0377)
rb_rs = Qnil;
else if (v == 0 && numlen >= 2) {
- rb_rs = rb_str_new2("");
+ rb_rs = rb_fstring_lit("");
}
else {
c = v & 0xff;
- rb_rs = rb_str_new(&c, 1);
+ rb_rs = rb_str_freeze(rb_str_new(&c, 1));
}
return s;
}
diff --git a/spec/ruby/command_line/dash_0_spec.rb b/spec/ruby/command_line/dash_0_spec.rb
new file mode 100755
index 0000000000..73c5e29004
--- /dev/null
+++ b/spec/ruby/command_line/dash_0_spec.rb
@@ -0,0 +1,13 @@
+require_relative '../spec_helper'
+
+describe "The -0 command line option" do
+ it "sets $/ and $-0" do
+ ruby_exe("puts $/, $-0", options: "-072").should == ":\n:\n"
+ end
+
+ ruby_version_is "3.5" do
+ it "sets $/ and $-0 as a frozen string" do
+ ruby_exe("puts $/.frozen?, $-0.frozen?", options: "-072").should == "true\ntrue\n"
+ end
+ end
+end
diff --git a/spec/ruby/language/predefined_spec.rb b/spec/ruby/language/predefined_spec.rb
index 9338a04715..f8645493b8 100644
--- a/spec/ruby/language/predefined_spec.rb
+++ b/spec/ruby/language/predefined_spec.rb
@@ -559,12 +559,39 @@ describe "Predefined global $/" do
$VERBOSE = @verbose
end
- it "can be assigned a String" do
- str = "abc"
- $/ = str
- $/.should equal(str)
+ ruby_version_is ""..."3.5" do
+ it "can be assigned a String" do
+ str = +"abc"
+ $/ = str
+ $/.should equal(str)
+ end
end
+ ruby_version_is "3.5" do
+ it "makes a new frozen String from the assigned String" do
+ string_subclass = Class.new(String)
+ str = string_subclass.new("abc")
+ str.instance_variable_set(:@ivar, 1)
+ $/ = str
+ $/.should.frozen?
+ $/.should be_an_instance_of(String)
+ $/.should_not.instance_variable_defined?(:@ivar)
+ $/.should == str
+ end
+
+ it "makes a new frozen String if it's not frozen" do
+ str = +"abc"
+ $/ = str
+ $/.should.frozen?
+ $/.should == str
+ end
+
+ it "assigns the given String if it's frozen and has no instance variables" do
+ str = "abc".freeze
+ $/ = str
+ $/.should equal(str)
+ end
+ end
it "can be assigned nil" do
$/ = nil
$/.should be_nil
@@ -608,10 +635,38 @@ describe "Predefined global $-0" do
$VERBOSE = @verbose
end
- it "can be assigned a String" do
- str = "abc"
- $-0 = str
- $-0.should equal(str)
+ ruby_version_is ""..."3.5" do
+ it "can be assigned a String" do
+ str = +"abc"
+ $-0 = str
+ $-0.should equal(str)
+ end
+ end
+
+ ruby_version_is "3.5" do
+ it "makes a new frozen String from the assigned String" do
+ string_subclass = Class.new(String)
+ str = string_subclass.new("abc")
+ str.instance_variable_set(:@ivar, 1)
+ $-0 = str
+ $-0.should.frozen?
+ $-0.should be_an_instance_of(String)
+ $-0.should_not.instance_variable_defined?(:@ivar)
+ $-0.should == str
+ end
+
+ it "makes a new frozen String if it's not frozen" do
+ str = +"abc"
+ $-0 = str
+ $-0.should.frozen?
+ $-0.should == str
+ end
+
+ it "assigns the given String if it's frozen and has no instance variables" do
+ str = "abc".freeze
+ $-0 = str
+ $-0.should equal(str)
+ end
end
it "can be assigned nil" do
diff --git a/string.c b/string.c
index 456ad4cad9..857d1e1085 100644
--- a/string.c
+++ b/string.c
@@ -1480,6 +1480,14 @@ rb_str_new_frozen_String(VALUE orig)
return str_new_frozen(rb_cString, orig);
}
+
+VALUE
+rb_str_frozen_bare_string(VALUE orig)
+{
+ if (RB_LIKELY(BARE_STRING_P(orig) && OBJ_FROZEN_RAW(orig))) return orig;
+ return str_new_frozen(rb_cString, orig);
+}
+
VALUE
rb_str_tmp_frozen_acquire(VALUE orig)
{