summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Evans <[email protected]>2024-09-20 14:57:56 -0700
committerBenoit Daloze <[email protected]>2024-09-21 20:00:23 +0200
commit9f574fa12f0cbe9d7aa4a11a6c7055ed32f02822 (patch)
treeda282c668d0426a805a293e4c5bcf78fc3a4a3ba
parent75ed086348da66e4cfe9488ae9ece5462dd2aef9 (diff)
Make Complex#{inspect,to_s} work correctly if real part #inspect returns frozen string
Make static f_format function take a non-frozen string to append to. This does not result in an additional allocation for #inspect, but it does result in an additional allocation for #to_s. Fixes [Bug #20337]
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/11657
-rw-r--r--complex.c9
-rw-r--r--test/ruby/test_complex.rb11
2 files changed, 15 insertions, 5 deletions
diff --git a/complex.c b/complex.c
index f562ed3161..b89c6f1f93 100644
--- a/complex.c
+++ b/complex.c
@@ -1593,16 +1593,15 @@ f_tpositive_p(VALUE x)
}
static VALUE
-f_format(VALUE self, VALUE (*func)(VALUE))
+f_format(VALUE self, VALUE s, VALUE (*func)(VALUE))
{
- VALUE s;
int impos;
get_dat1(self);
impos = f_tpositive_p(dat->imag);
- s = (*func)(dat->real);
+ rb_str_concat(s, (*func)(dat->real));
rb_str_cat2(s, !impos ? "-" : "+");
rb_str_concat(s, (*func)(f_abs(dat->imag)));
@@ -1629,7 +1628,7 @@ f_format(VALUE self, VALUE (*func)(VALUE))
static VALUE
nucomp_to_s(VALUE self)
{
- return f_format(self, rb_String);
+ return f_format(self, rb_usascii_str_new2(""), rb_String);
}
/*
@@ -1651,7 +1650,7 @@ nucomp_inspect(VALUE self)
VALUE s;
s = rb_usascii_str_new2("(");
- rb_str_concat(s, f_format(self, rb_inspect));
+ f_format(self, s, rb_inspect);
rb_str_cat2(s, ")");
return s;
diff --git a/test/ruby/test_complex.rb b/test/ruby/test_complex.rb
index c0cfb73235..bb131cee91 100644
--- a/test/ruby/test_complex.rb
+++ b/test/ruby/test_complex.rb
@@ -741,6 +741,17 @@ class Complex_Test < Test::Unit::TestCase
assert_equal('(1+2i)', c.inspect)
end
+ def test_inspect_to_s_frozen_bug_20337
+ assert_separately([], <<~'RUBY')
+ class Numeric
+ def inspect = super.freeze
+ end
+ c = Complex(Numeric.new, 1)
+ assert_match(/\A\(#<Numeric:/, c.inspect)
+ assert_match(/\A#<Numeric:/, c.to_s)
+ RUBY
+ end
+
def test_marshal
c = Complex(1,2)