From cf12aff0593a0aa70d957b96f03df8288c025938 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 5 Dec 2025 00:27:45 +0900 Subject: [PATCH] [Bug #21764] Propagate the encoding of ID to warning --- io.c | 20 ++++---------------- spec/ruby/language/predefined_spec.rb | 16 ++++++++++++++-- string.c | 17 ++++++++++++++++- test/ruby/test_string.rb | 14 +++++++++++++- 4 files changed, 47 insertions(+), 20 deletions(-) diff --git a/io.c b/io.c index a5a8139f29..549e7e1317 100644 --- a/io.c +++ b/io.c @@ -8641,31 +8641,19 @@ rb_f_printf(int argc, VALUE *argv, VALUE _) return Qnil; } -static void -deprecated_str_setter(VALUE val, ID id, VALUE *var) -{ - rb_str_setter(val, id, &val); - if (!NIL_P(val)) { - rb_warn_deprecated("'%s'", NULL, rb_id2name(id)); - } - *var = val; -} +extern void rb_deprecated_str_setter(VALUE val, ID id, VALUE *var); static void deprecated_rs_setter(VALUE val, ID id, VALUE *var) { + rb_deprecated_str_setter(val, id, &val); 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; } @@ -15730,7 +15718,7 @@ Init_IO(void) rb_define_method(rb_cIO, "initialize", rb_io_initialize, -1); rb_output_fs = Qnil; - rb_define_hooked_variable("$,", &rb_output_fs, 0, deprecated_str_setter); + rb_define_hooked_variable("$,", &rb_output_fs, 0, rb_deprecated_str_setter); rb_default_rs = rb_fstring_lit("\n"); /* avoid modifying RS_default */ rb_vm_register_global_object(rb_default_rs); @@ -15740,7 +15728,7 @@ Init_IO(void) 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_hooked_variable("$\\", &rb_output_rs, 0, rb_deprecated_str_setter); rb_define_virtual_variable("$_", get_LAST_READ_LINE, set_LAST_READ_LINE); rb_gvar_ractor_local("$_"); diff --git a/spec/ruby/language/predefined_spec.rb b/spec/ruby/language/predefined_spec.rb index f2488615aa..fc1667a38f 100644 --- a/spec/ruby/language/predefined_spec.rb +++ b/spec/ruby/language/predefined_spec.rb @@ -748,6 +748,10 @@ describe "Predefined global $/" do it "raises a TypeError if assigned a boolean" do -> { $/ = true }.should raise_error(TypeError, 'value of $/ must be String') end + + it "warns if assigned non-nil" do + -> { $/ = "_" }.should complain(/warning: (?:non-nil )?[`']\$\/' is deprecated/) + end end describe "Predefined global $-0" do @@ -825,6 +829,10 @@ describe "Predefined global $-0" do it "raises a TypeError if assigned a boolean" do -> { $-0 = true }.should raise_error(TypeError, 'value of $-0 must be String') end + + it "warns if assigned non-nil" do + -> { $-0 = "_" }.should complain(/warning: (?:non-nil )?[`']\$-0' is deprecated/) + end end describe "Predefined global $\\" do @@ -864,6 +872,10 @@ describe "Predefined global $\\" do -> { $\ = 1 }.should raise_error(TypeError, 'value of $\ must be String') -> { $\ = true }.should raise_error(TypeError, 'value of $\ must be String') end + + it "warns if assigned non-nil" do + -> { $\ = "_" }.should complain(/warning: (?:non-nil )?[`']\$\\' is deprecated/) + end end describe "Predefined global $," do @@ -880,7 +892,7 @@ describe "Predefined global $," do end it "warns if assigned non-nil" do - -> { $, = "_" }.should complain(/warning: [`']\$,' is deprecated/) + -> { $, = "_" }.should complain(/warning: (?:non-nil )?[`']\$,' is deprecated/) end end @@ -917,7 +929,7 @@ describe "Predefined global $;" do end it "warns if assigned non-nil" do - -> { $; = "_" }.should complain(/warning: [`']\$;' is deprecated/) + -> { $; = "_" }.should complain(/warning: (?:non-nil )?[`']\$;' is deprecated/) end end diff --git a/string.c b/string.c index 0370fc5d1e..065e8c4d8c 100644 --- a/string.c +++ b/string.c @@ -11375,6 +11375,21 @@ rb_str_setter(VALUE val, ID id, VALUE *var) *var = val; } +static void +nil_setter_warning(ID id) +{ + rb_warn_deprecated("'%"PRIsVALUE"'", NULL, rb_id2str(id)); +} + +void +rb_deprecated_str_setter(VALUE val, ID id, VALUE *var) +{ + rb_str_setter(val, id, var); + if (!NIL_P(*var)) { + nil_setter_warning(id); + } +} + static void rb_fs_setter(VALUE val, ID id, VALUE *var) { @@ -11385,7 +11400,7 @@ rb_fs_setter(VALUE val, ID id, VALUE *var) rb_id2str(id)); } if (!NIL_P(val)) { - rb_warn_deprecated("'$;'", NULL); + nil_setter_warning(id); } *var = val; } diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb index 50dc5ec2f9..6fdc2bdaa8 100644 --- a/test/ruby/test_string.rb +++ b/test/ruby/test_string.rb @@ -1886,6 +1886,17 @@ CODE assert_raise_with_message(TypeError, /\$;/) { $; = [] } + name = "\u{5206 5217}" + assert_separately([], "#{<<~"do;"}\n#{<<~"end;"}") + do; + alias $#{name} $; + assert_deprecated_warning(/\\$#{name}/) { $#{name} = "" } + assert_raise_with_message(TypeError, /\\$#{name}/) { $#{name} = 1 } + end; + end + + def test_fs_gc + return unless @cls == String assert_separately(%W[-W0], "#{<<~"begin;"}\n#{<<~'end;'}") bug = '[ruby-core:79582] $; must not be GCed' @@ -2761,7 +2772,7 @@ CODE assert_equal([S("abcdb"), S("c"), S("e")], S("abcdbce").rpartition(/b\Kc/)) end - def test_fs_setter + def test_rs return unless @cls == String assert_raise(TypeError) { $/ = 1 } @@ -2769,6 +2780,7 @@ CODE assert_separately([], "#{<<~"do;"}\n#{<<~"end;"}") do; alias $#{name} $/ + assert_deprecated_warning(/\\$#{name}/) { $#{name} = "" } assert_raise_with_message(TypeError, /\\$#{name}/) { $#{name} = 1 } end; end