Jeremy Evans 41b8e440e7 Support backwards compatibility for Set subclasses
For subclasses from Set, require `set/subclass_compatible`, and
extend the subclass and include a module in it that makes it more
backwards compatible with the pure Ruby Set implementation used
before Ruby 4.

The module included in the subclass contains a near-copy of the
previous Set implementation, with the following changes:

* Accesses to `@hash` are generally replaced with `super` calls. In
  some cases, they are replaced with a call to another instance method.
* Some methods that only accessed `@hash` and nothing else are not
  defined, so they inherit behavior from core Set.
* The previous `Set#divide` implementation is not used, to avoid
  depending on tsort.

This fixes the following two issues:

* [Bug #21375] Set[] does not call #initialize
* [Bug #21396] Set#initialize should call Set#add on items passed in

It should also fix the vast majority of backwards compatibility issues
in other cases where code subclassed Set and depended on implementation
details (such as which methods call which other methods).

This does not affect Set internals, so Set itself remains fast. For
users who want to subclass Set but do not need to worry about
backwards compatibility, they can subclass from Set::CoreSet, a Set
subclass that does not have the backward compatibility layer included.
2025-11-20 23:54:29 +09:00
..