Fix some #eql? correctness issues

The implementation of #eql? and #hash should ensure that if a.eql?(b),
then a.hash == b.hash, but #eql? itself should not *depend* on #hash.

For example, given

  class Thingy
    def eql?
      instance_of?(other.class) && hash == other.hash
    end

    def hash
      [name, *tags].hash
    end
  end

if #hash produces a collision for different values of [name, *tags], two
Thingy objects will appear to be eql?, even though this is not the case.
Instead, #eql? should depend on the equality of name and tags directly.
This commit is contained in:
Jack Nagel 2013-06-27 01:18:32 -05:00
parent ad291d7f06
commit 10949ad75d
4 changed files with 17 additions and 3 deletions

View File

@ -21,7 +21,7 @@ class Dependency
end
def eql?(other)
instance_of?(other.class) && hash == other.hash
instance_of?(other.class) && name == other.name
end
def hash

View File

@ -20,7 +20,7 @@ class Option
end
def eql?(other)
other.is_a?(self.class) && hash == other.hash
instance_of?(other.class) && name == other.name
end
def hash

View File

@ -54,7 +54,7 @@ class Requirement
end
def eql?(other)
instance_of?(other.class) && hash == other.hash
instance_of?(other.class) && name == other.name && tags == other.tags
end
def hash

View File

@ -121,4 +121,18 @@ class RequirementTests < Test::Unit::TestCase
req.to_dependency.modify_build_environment
end
end
def test_eql
a, b = Requirement.new, Requirement.new
assert a.eql?(b)
assert b.eql?(a)
assert_equal a.hash, b.hash
end
def test_not_eql
a, b = Requirement.new([:optional]), Requirement.new
assert_not_equal a.hash, b.hash
assert !a.eql?(b)
assert !b.eql?(a)
end
end