Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: rubinius/rubinius
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 47fcb429cb0f
Choose a base ref
...
head repository: rubinius/rubinius
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 7f7d57b482a3
Choose a head ref
  • 4 commits
  • 3 files changed
  • 2 contributors

Commits on Jun 26, 2015

  1. Changed Comparable#== to use a recursion guard.

    * Instead of rescuing a SystemStackError.
    eregon committed Jun 26, 2015
    Copy the full SHA
    859acc0 View commit details
  2. Copy the full SHA
    339f429 View commit details
  3. Copy the full SHA
    9e3c437 View commit details
  4. Merge pull request #3452 from eregon/comparable_equal_recursion

    Change Comparable#== to use a recursion guard
    brixen committed Jun 26, 2015
    Copy the full SHA
    7f7d57b View commit details
Showing with 58 additions and 6 deletions.
  1. +8 −6 kernel/common/comparable.rb
  2. +31 −0 spec/ruby/core/comparable/equal_value_spec.rb
  3. +19 −0 spec/ruby/core/comparable/fixtures/classes.rb
14 changes: 8 additions & 6 deletions kernel/common/comparable.rb
Original file line number Diff line number Diff line change
@@ -2,14 +2,16 @@ module Comparable
def ==(other)
return true if equal?(other)

begin
unless comp = (self <=> other)
return false if Thread.detect_recursion(self, other) do
begin
unless comp = (self <=> other)
return false
end

return Comparable.compare_int(comp) == 0
rescue StandardError
return false
end

return Comparable.compare_int(comp) == 0
rescue StandardError, SystemStackError
return false
end
end

31 changes: 31 additions & 0 deletions spec/ruby/core/comparable/equal_value_spec.rb
Original file line number Diff line number Diff line change
@@ -65,4 +65,35 @@ def @raise_not_standard_error.<=>(b) raise SyntaxError, "test"; end
(@raise_sub_standard_error == @b).should be_false
end
end

context "when #<=> is not defined" do
before :each do
@a = ComparableSpecs::WithoutCompareDefined.new
@b = ComparableSpecs::WithoutCompareDefined.new
end

it "returns true for identical objects" do
@a.should == @a
end

it "returns false and does not recurse infinitely" do
@a.should_not == @b
end
end

context "when #<=> calls super" do
before :each do
@a = ComparableSpecs::CompareCallingSuper.new
@b = ComparableSpecs::CompareCallingSuper.new
end

it "returns true for identical objects" do
@a.should == @a
end

it "calls the defined #<=> only once for different objects" do
@a.should_not == @b
@a.calls.should == 1
end
end
end
19 changes: 19 additions & 0 deletions spec/ruby/core/comparable/fixtures/classes.rb
Original file line number Diff line number Diff line change
@@ -12,4 +12,23 @@ def <=>(other)
self.value <=> other.value
end
end

class WithoutCompareDefined
include Comparable
end

class CompareCallingSuper
include Comparable

attr_reader :calls

def initialize
@calls = 0
end

def <=>(other)
@calls += 1
super(other)
end
end
end