From 6ffc045a817fbdf04a6945d3c260b55b0fa1fd1e Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Sun, 8 Sep 2019 11:53:27 +0200 Subject: [PATCH] [EXPERIMENTAL] Make Symbol#to_s return a frozen String * Always the same frozen String for a given Symbol. * Avoids extra allocations whenever calling Symbol#to_s. * See [Feature #16150] --- NEWS | 8 ++++++++ spec/ruby/core/symbol/shared/id2name.rb | 17 +++++++++++++++++ string.c | 5 +++-- test/-ext-/string/test_capacity.rb | 4 +++- 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 70c5ff6bdf..4e168518ca 100644 --- a/NEWS +++ b/NEWS @@ -197,6 +197,14 @@ RubyVM:: * RubyVM.resolve_feature_path moved to $LOAD_PATH.resolve_feature_path. [Feature #15903] [Feature #15230] +Symbol:: + + Modified method:: + + * Symbol#to_s now always returns a frozen String. The returned String is + always the same for a given Symbol. This change is experimental. + [Feature #16150] + Time:: New methods:: diff --git a/spec/ruby/core/symbol/shared/id2name.rb b/spec/ruby/core/symbol/shared/id2name.rb index 47f97bd332..a0e190a680 100644 --- a/spec/ruby/core/symbol/shared/id2name.rb +++ b/spec/ruby/core/symbol/shared/id2name.rb @@ -6,4 +6,21 @@ describe :symbol_id2name, shared: true do :@ruby.send(@method).should == "@ruby" :@@ruby.send(@method).should == "@@ruby" end + + ruby_version_is "2.7" do + it "returns a frozen String" do + :my_symbol.to_s.frozen?.should == true + :"dynamic symbol #{6 * 7}".to_s.frozen?.should == true + end + + it "always returns the same String for a given Symbol" do + s1 = :my_symbol.to_s + s2 = :my_symbol.to_s + s1.should equal(s2) + + s1 = :"dynamic symbol #{6 * 7}".to_s + s2 = :"dynamic symbol #{2 * 3 * 7}".to_s + s1.should equal(s2) + end + end end diff --git a/string.c b/string.c index 367773f0f5..3f0e69689c 100644 --- a/string.c +++ b/string.c @@ -10869,7 +10869,8 @@ sym_inspect(VALUE sym) * sym.id2name -> string * sym.to_s -> string * - * Returns the name or string corresponding to sym. + * Returns a frozen string corresponding to sym. + * The returned String is always the same String instance for a given Symbol. * * :fred.id2name #=> "fred" * :ginger.to_s #=> "ginger" @@ -10879,7 +10880,7 @@ sym_inspect(VALUE sym) VALUE rb_sym_to_s(VALUE sym) { - return str_new_shared(rb_cString, rb_sym2str(sym)); + return rb_sym2str(sym); } diff --git a/test/-ext-/string/test_capacity.rb b/test/-ext-/string/test_capacity.rb index df59e76778..f5830a033b 100644 --- a/test/-ext-/string/test_capacity.rb +++ b/test/-ext-/string/test_capacity.rb @@ -14,7 +14,9 @@ class Test_StringCapacity < Test::Unit::TestCase end def test_capacity_shared - assert_equal 0, capa(:abcdefghijklmnopqrstuvwxyz.to_s) + str = :abcdefghijklmnopqrstuvwxyz.to_s.dup + assert Bug::String.shared_string? str + assert_equal 0, capa(str) end def test_capacity_normal