cats icon indicating copy to clipboard operation
cats copied to clipboard

Remove "Chain#hashCode is consistent with List#hashCode"

Open rossabaker opened this issue 10 months ago • 6 comments

It's no longer true as of Scala 2.13.16, and was probably overspecified in the first place.

Fixes #4716.

rossabaker avatar Feb 21 '25 21:02 rossabaker

was probably overspecified in the first place.

Agree with this.

It's no longer true as of Scala 2.13.16

Isn't that because they fixed a hashing bug, that we may want to fix too?

  • https://github.com/scala/bug/issues/12826

Edit (aha!):

  • https://github.com/typelevel/cats/pull/4719

armanbilge avatar Feb 21 '25 21:02 armanbilge

That's a fair point. I don't care about equality, but being alerted to the improved hash algorithm was nice. I'd also be willing to leave it with a comment so it's less of a chase for the next maintainer who hits this.

rossabaker avatar Feb 21 '25 22:02 rossabaker

Honestly, I'm not sure I'm following how come it was assumed that

Chain#hashCode is consistent with List#hashCode

in the first place? What was the justification for that? I mean, Chain and List are different types, they don't have to have same hash codes even if they contain same elements, or do they?

satorg avatar Feb 21 '25 23:02 satorg

They don't need the same hash codes unless they're equal, which is not a goal, shouldn't be a goal, and would be quite a challenge to do lawfully even if it were a goal.

rossabaker avatar Feb 21 '25 23:02 rossabaker

I think the original idea is that it is easy to mess up a hash and make it too weak. Also it would be easy to make a structural hash to cares about the construction order which we don't want. In this case we had a test that asserts the hashCode is the same as toList.hashCode which proves it can't be a terrible hash (it can't have a few of the failure modes).

So it's not a terrible idea but the weakness is obvious now: we don't control the thing we are asserting it matches and we don't actually need it to match just a sufficient condition for it to probably be a good hash.

johnynek avatar Feb 22 '25 00:02 johnynek

@johnynek ,

Also it would be easy to make a structural hash to cares about the construction order which we don't want.

Oh, I see now, that is a valid point. But in order to check it properly, I guess the test should look somewhat like this:

forAll { (x: Chain[Int]) =>
  assert(x.hashCode === Chain.fromIterableOnce(x.iterator).hashCode)
}

– that way we make sure Chain#hashCode doesn't depend on its structure, but also it doesn't depend on the List implementation either. Wdyt?

satorg avatar Feb 22 '25 00:02 satorg