Issue #21921 has been updated by maxfelsher (Max Felsher).
An entry `h0[k0]` in one hash is equal to an entry `h1[k1]` in another hash if and only if the two keys are equal (`k0 == k1`) and their two values are equal (`h0[k0] == h1[h1]`).
This sentence is merely defining the phrase "is equal to". It does not describe the hash lookup mechanism itself.
It doesn't just say "equal", it specifically mentions `k0 == k1`; might be worth disambiguating to "if the two keys are equal (either `k0.eql? k1` or `k0.equal? k1`)"
Yes, I read the spec as saying "Given two hashes h0 and h1, and two objects k0 and k1 that are keys in h0 and h1 respectively, the h0[k0] entry and h1[k1] entry are equal if the following Ruby code evaluates to true: `k0 == k1 && h0[k0] == h1[k1]`." And therefore the spec's implementation of `<=` would be equivalent to the following (for every entry in h0, there is at least one equal entry in h1): ``` ruby def subset?(h0, h1) h0.all? do |k0, _v0| h1.any? do |k1, _v1| k0 == k1 && h0[k0] == h1[k1] end end end ``` Given such a specification, a hash being compare-by-identity wouldn't make a difference in the logic, since everything is being compared by `==`. I assume that this implementation scales pretty poorly, though. I think the current implementation is closer to this: ``` ruby def subset?(h0, h1) h0.all? do |k0, _v0| h1.key?(k0) && h0[k0] == h1[k0] # Note the use of k0 throughout end end ``` In this one, compare-by-identity does matter, since you're using the keys from h0 to look up values in h1. It seems like either the specification or the implementation should change to be consistent with each other? **Side note:** the specification actually says `h0[k0] == h1[h1]`, but I've assumed that there's a typo in the last variable name and it should be `h0[k0] == h1[k1]`. If that assumption is correct, it seems like at the very least that typo should be corrected? ---------------------------------------- Bug #21921: Hash inconsistent ==, >=, <= behavior https://bugs.ruby-lang.org/issues/21921#change-116533 * Author: cohen (Cohen Carlisle) * Status: Open * ruby -v: ruby 4.0.1 (2026-01-13 revision e04267a14b) +PRISM [x86_64-linux] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN ---------------------------------------- Hash seems to have very inconsistent behavior for `==`, `>=`, and `<=`. Given that below h1 == h2 is `false` and that they have the same number of keys, I would expect `<=` and `>=` to also be `false`. However, surprisingly `h1 <= h2` and `h2 >= h1` are `true`, while all other permutations are `false`. ``` h1 = {}.compare_by_identity.tap { _1["one"] = 1 } # => {"one" => 1} h2 = {"one" => 1} # => {"one" => 1} h1 == h2 # => false h2 == h1 # => false h1 >= h2 # => false h1 <= h2 # => true h2 >= h1 # => true h2 <= h1 # => false ``` -- https://bugs.ruby-lang.org/