Issue #14263 has been updated by styrmis (Stefan Magnuson).

File test-14264.rb added

We (myself and [Lewis Buckley](https://github.com/lewispb)) investigated this issue as part of the Ruby Hack Day at Cookpad.

We were able to replicate the issue on Ruby 2.6 (trunk)ˇ˝digging a bit deeper we found that the unexpected behaviour only occurs when both arrays have <= 16 elements.

This is because in Ruby 2.5 a [performance enhancement was added](https://bugs.ruby-lang.org/issues/13884) to avoid building a hash when the array sizes are small.

The [version for small arrays](https://github.com/ruby/ruby/blob/trunk/array.c#L4230) compares elements [using `#eql?`](https://github.com/ruby/ruby/blob/trunk/array.c#L4230) whereas the implementation in 2.4 [defers to the `Hash` implementation of equality checking](https://github.com/ruby/ruby/blob/trunk/array.c#L4246) which appears to use the hash directly (and not the `#eql?` method).

We discussed with Matz during the event, and the conclusion at the time was that:

- The example as given has an inconsistent implementation (between the implementation of `Val#eql?` and `Val#hash`), and as such the behaviour is undefined, and could reasonably change between versions
- The documentation for [`Object#eql?`](https://ruby-doc.org/core-2.5.0/Object.html#method-i-eql-3F) could be extended to make this clearer

So one possible improvement would be to update the documentation for `Object#eql?` to make clear that when `#eql?` is overridden it should be kept consistent with the result of a comparison of the `#hash` of two objects.

Another possible solution might be to make both variants (for both large and small arrays) use the same method of comparison, i.e. both `#eql?` or both hash equivalence.



----------------------------------------
Bug #14263: Array Intersection does not seem to use hash
https://bugs.ruby-lang.org/issues/14263#change-71142

* Author: gkellogg (Gregg Kellogg)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
* ruby -v: 2.5.0
* Backport: 2.3: UNKNOWN, 2.4: UNKNOWN, 2.5: UNKNOWN
----------------------------------------
According to the documentation for Array#&, comparison is done using hash and eql? However, this does not seem to be the case in 2.5.0.

If two instances are .eql? but their hashes are not, an array & should be empty:

~~~ ruby
([Var.new('a')] & [Var.new('b')]).empty?

~~~

This test works in 2.4.2 (and all earlier versions), but fails in 2.5.0. See attached script.

---Files--------------------------------
array_intersection.rb (535 Bytes)
test-14264.rb (956 Bytes)


-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>