Skip to content

Commit 8b3640b

Browse files
committed
[GR-18163] Fix {Rational,Complex}#{marshal_dump,marshal_load} to be compatible with CRuby
PullRequest: truffleruby/3967 (cherry picked from commit 9697b43)
1 parent 0acdf6b commit 8b3640b

File tree

5 files changed

+28
-38
lines changed

5 files changed

+28
-38
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ Compatibility:
4242
* Add `Module#const_added` (#3039, @itarato).
4343
* Show the pointer size information (if available) in `FFI::Pointer#inspect` (@nirvdrum).
4444
* Implement performance warnings (`Warning[:performance]`) like in CRuby 3.3 (@eregon).
45+
* The output of `Marshal.dump` is now compatible with CRuby for `Rational` and `Complex` instances (#3228, @eregon).
4546

4647
Performance:
4748

spec/ruby/core/marshal/dump_spec.rb

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,18 @@ def _dump(level)
271271
end
272272
end
273273

274+
describe "with a Rational" do
275+
it "dumps a Rational" do
276+
Marshal.dump(Rational(2, 3)).should == "\x04\bU:\rRational[\ai\ai\b"
277+
end
278+
end
279+
280+
describe "with a Complex" do
281+
it "dumps a Complex" do
282+
Marshal.dump(Complex(2, 3)).should == "\x04\bU:\fComplex[\ai\ai\b"
283+
end
284+
end
285+
274286
describe "with a String" do
275287
it "dumps a blank String" do
276288
Marshal.dump("".force_encoding("binary")).should == "\004\b\"\000"
@@ -769,7 +781,6 @@ def finalizer.noop(_)
769781
end
770782

771783
describe "when passed an IO" do
772-
773784
it "writes the serialized data to the IO-Object" do
774785
(obj = mock('test')).should_receive(:write).at_least(1)
775786
Marshal.dump("test", obj)
@@ -792,8 +803,6 @@ def finalizer.noop(_)
792803
obj.should_receive(:binmode).at_least(1)
793804
Marshal.dump("test", obj)
794805
end
795-
796-
797806
end
798807

799808
describe "when passed a StringIO" do

spec/ruby/core/marshal/shared/load.rb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,13 +1034,17 @@ def io.binmode; raise "binmode"; end
10341034

10351035
describe "for a Rational" do
10361036
it "loads" do
1037-
Marshal.send(@method, Marshal.dump(Rational(1, 3))).should == Rational(1, 3)
1037+
r = Marshal.send(@method, Marshal.dump(Rational(1, 3)))
1038+
r.should == Rational(1, 3)
1039+
r.should.frozen?
10381040
end
10391041
end
10401042

10411043
describe "for a Complex" do
10421044
it "loads" do
1043-
Marshal.send(@method, Marshal.dump(Complex(4, 3))).should == Complex(4, 3)
1045+
c = Marshal.send(@method, Marshal.dump(Complex(4, 3)))
1046+
c.should == Complex(4, 3)
1047+
c.should.frozen?
10441048
end
10451049
end
10461050

src/main/ruby/truffleruby/core/complex.rb

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -311,23 +311,14 @@ def fdiv(other)
311311
self / other
312312
end
313313

314-
def marshal_dump
315-
ary = [real, imag]
316-
instance_variables.each do |ivar|
317-
ary.instance_variable_set(ivar, instance_variable_get(ivar))
318-
end
319-
ary
314+
private def marshal_dump
315+
[@real, @imag]
320316
end
321-
private :marshal_dump
322317

323-
def marshal_load(ary)
318+
private def marshal_load(ary)
324319
@real, @imag = ary
325-
ary.instance_variables.each do |ivar|
326-
instance_variable_set(ivar, ary.instance_variable_get(ivar))
327-
end
328-
self
320+
Primitive.freeze(self)
329321
end
330-
private :marshal_load
331322

332323
def <=>(other)
333324
if imag == 0 && Primitive.is_a?(other, Numeric)

src/main/ruby/truffleruby/core/rational.rb

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -406,31 +406,17 @@ def initialize(num, den)
406406
@denominator = den
407407
Primitive.freeze(self)
408408
end
409-
private :initialize
410409

411-
def marshal_dump
412-
ary = [@numerator, @denominator]
413-
414-
instance_variables.each do |ivar|
415-
ary.instance_variable_set(ivar, instance_variable_get(ivar))
416-
end
417-
418-
ary
410+
private def marshal_dump
411+
[@numerator, @denominator]
419412
end
420-
private :marshal_dump
421413

422-
def marshal_load(ary)
414+
private def marshal_load(ary)
423415
@numerator, @denominator = ary
424-
425-
ary.instance_variables.each do |ivar|
426-
instance_variable_set(ivar, ary.instance_variable_get(ivar))
427-
end
428-
429-
self
416+
Primitive.freeze(self)
430417
end
431-
private :marshal_load
432418

433-
def with_precision(method, n, **kwargs)
419+
private def with_precision(method, n, **kwargs)
434420
raise TypeError, 'not an integer' unless Primitive.is_a?(n, Integer)
435421

436422
p = 10 ** n
@@ -445,5 +431,4 @@ def with_precision(method, n, **kwargs)
445431
r = Rational(wp, p)
446432
n < 1 ? r.to_i : r
447433
end
448-
private :with_precision
449434
end

0 commit comments

Comments
 (0)