<feed xmlns='http://www.w3.org/2005/Atom'>
<title>ruby.git/test/ruby/test_set.rb, branch v4.0.2</title>
<subtitle>The Ruby Programming Language</subtitle>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/'/>
<entry>
<title>Revert the override of Enumerator#to_set that performed size checks</title>
<updated>2025-12-17T08:30:24+00:00</updated>
<author>
<name>Akinori Musha</name>
<email>knu@idaemons.org</email>
</author>
<published>2025-12-17T08:30:24+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=79f36c544a0431d9b76c3c11a5f622383eaca7bd'/>
<id>79f36c544a0431d9b76c3c11a5f622383eaca7bd</id>
<content type='text'>
[Bug #21780]
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
[Bug #21780]
</pre>
</div>
</content>
</entry>
<entry>
<title>Fix Set#^ to not mutate its argument (#15296)</title>
<updated>2025-12-11T16:38:39+00:00</updated>
<author>
<name>Gil Desmarais</name>
<email>gildesmarais@users.noreply.github.com</email>
</author>
<published>2025-12-11T16:38:39+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=b5604833a37bf8cac132906fbf8297d6d4ae9976'/>
<id>b5604833a37bf8cac132906fbf8297d6d4ae9976</id>
<content type='text'>
* test(set): add test Set#xor does not mutate other_set

* Fix Set#^ to not mutate its argument
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
* test(set): add test Set#xor does not mutate other_set

* Fix Set#^ to not mutate its argument
</pre>
</div>
</content>
</entry>
<entry>
<title>Support backwards compatibility for Set subclasses</title>
<updated>2025-11-20T14:54:29+00:00</updated>
<author>
<name>Jeremy Evans</name>
<email>code@jeremyevans.net</email>
</author>
<published>2025-11-18T01:58:26+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=41b8e440e7f2c5d3d1c1a9644de4bdc06a343724'/>
<id>41b8e440e7f2c5d3d1c1a9644de4bdc06a343724</id>
<content type='text'>
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.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
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.
</pre>
</div>
</content>
</entry>
<entry>
<title>Add size checks to Range#to_set and Enumerator#to_set [Bug #21654]</title>
<updated>2025-11-13T13:00:07+00:00</updated>
<author>
<name>Akinori Musha</name>
<email>knu@idaemons.org</email>
</author>
<published>2025-11-13T11:01:37+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=61500c6f48135ef018f5e496ff292a86b0043c65'/>
<id>61500c6f48135ef018f5e496ff292a86b0043c65</id>
<content type='text'>
These two class are most common sources of infinite sequences.  This change should effectively prevent accidental infinite loops when calling to_set on them. [Bug #21513]
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
These two class are most common sources of infinite sequences.  This change should effectively prevent accidental infinite loops when calling to_set on them. [Bug #21513]
</pre>
</div>
</content>
</entry>
<entry>
<title>Revert "[Bug #21513] Raise on converting endless range to set"</title>
<updated>2025-11-13T13:00:07+00:00</updated>
<author>
<name>Akinori Musha</name>
<email>knu@idaemons.org</email>
</author>
<published>2025-11-13T10:13:10+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=25c871fddf430d18a1f0a794a0f81598e9b79727'/>
<id>25c871fddf430d18a1f0a794a0f81598e9b79727</id>
<content type='text'>
This reverts commit d4020dd5faf28486123853e7f00c36139fc07793, which introduced performance regression for objects like ActiveRecord::Relation by calling the costly #size method on them.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
This reverts commit d4020dd5faf28486123853e7f00c36139fc07793, which introduced performance regression for objects like ActiveRecord::Relation by calling the costly #size method on them.
</pre>
</div>
</content>
</entry>
<entry>
<title>set.c: Store `set_table-&gt;bins` at the end of `set_table-&gt;entries`</title>
<updated>2025-08-12T19:56:57+00:00</updated>
<author>
<name>Jean Boussier</name>
<email>jean.boussier@gmail.com</email>
</author>
<published>2025-08-07T11:30:53+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=85c52079aa35a1d2e063a5b40eebe91701c8cb9e'/>
<id>85c52079aa35a1d2e063a5b40eebe91701c8cb9e</id>
<content type='text'>
This saves one pointer in `struct set_table`, which would allow
`Set` objects to still fit in 80B TypedData slots even if RTypedData
goes from 32B to 40B large.

The existing set benchmark seem to show this doesn't have a very
significant impact. Smaller sets are a bit faster, larger sets
a bit slower.

It seem consistent over multiple runs, but it's unclear how much
of that is just error margin.

```
compare-ruby: ruby 3.5.0dev (2025-08-12T02:14:57Z master 428937a536) +YJIT +PRISM [arm64-darwin24]
built-ruby: ruby 3.5.0dev (2025-08-12T07:22:26Z set-entries-bounds da30024fdc) +YJIT +PRISM [arm64-darwin24]
warming up........

|                         |compare-ruby|built-ruby|
|:------------------------|-----------:|---------:|
|new_0                    |     15.459M|   15.823M|
|                         |           -|     1.02x|
|new_10                   |      3.484M|    3.574M|
|                         |           -|     1.03x|
|new_100                  |    546.992k|  564.679k|
|                         |           -|     1.03x|
|new_1000                 |     49.391k|   48.169k|
|                         |       1.03x|         -|
|aref_0                   |     18.643M|   19.350M|
|                         |           -|     1.04x|
|aref_10                  |      5.941M|    6.006M|
|                         |           -|     1.01x|
|aref_100                 |    822.197k|  814.219k|
|                         |       1.01x|         -|
|aref_1000                |     83.230k|   79.411k|
|                         |       1.05x|         -|
```
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
This saves one pointer in `struct set_table`, which would allow
`Set` objects to still fit in 80B TypedData slots even if RTypedData
goes from 32B to 40B large.

The existing set benchmark seem to show this doesn't have a very
significant impact. Smaller sets are a bit faster, larger sets
a bit slower.

It seem consistent over multiple runs, but it's unclear how much
of that is just error margin.

```
compare-ruby: ruby 3.5.0dev (2025-08-12T02:14:57Z master 428937a536) +YJIT +PRISM [arm64-darwin24]
built-ruby: ruby 3.5.0dev (2025-08-12T07:22:26Z set-entries-bounds da30024fdc) +YJIT +PRISM [arm64-darwin24]
warming up........

|                         |compare-ruby|built-ruby|
|:------------------------|-----------:|---------:|
|new_0                    |     15.459M|   15.823M|
|                         |           -|     1.02x|
|new_10                   |      3.484M|    3.574M|
|                         |           -|     1.03x|
|new_100                  |    546.992k|  564.679k|
|                         |           -|     1.03x|
|new_1000                 |     49.391k|   48.169k|
|                         |       1.03x|         -|
|aref_0                   |     18.643M|   19.350M|
|                         |           -|     1.04x|
|aref_10                  |      5.941M|    6.006M|
|                         |           -|     1.01x|
|aref_100                 |    822.197k|  814.219k|
|                         |       1.01x|         -|
|aref_1000                |     83.230k|   79.411k|
|                         |       1.05x|         -|
```
</pre>
</div>
</content>
</entry>
<entry>
<title>[Bug #21513] Raise on converting endless range to set</title>
<updated>2025-07-29T09:42:18+00:00</updated>
<author>
<name>viralpraxis</name>
<email>iaroslav2k@gmail.com</email>
</author>
<published>2025-07-15T21:59:22+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=d4020dd5faf28486123853e7f00c36139fc07793'/>
<id>d4020dd5faf28486123853e7f00c36139fc07793</id>
<content type='text'>
ref: https://bugs.ruby-lang.org/issues/21513

Before this patch, trying to convert endless range (e.g. `(1..)`) to set
(using `to_set`) would hang
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
ref: https://bugs.ruby-lang.org/issues/21513

Before this patch, trying to convert endless range (e.g. `(1..)`) to set
(using `to_set`) would hang
</pre>
</div>
</content>
</entry>
<entry>
<title>Include Set subclass name in Set#inspect output</title>
<updated>2025-06-25T00:21:07+00:00</updated>
<author>
<name>Jeremy Evans</name>
<email>code@jeremyevans.net</email>
</author>
<published>2025-06-05T15:29:56+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=7c3bbfcddb05b0eb7cca7ac32efd2fc07e1af6ec'/>
<id>7c3bbfcddb05b0eb7cca7ac32efd2fc07e1af6ec</id>
<content type='text'>
Fixes [Bug #21377]

Co-authored-by: zzak &lt;zzak@hey.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Fixes [Bug #21377]

Co-authored-by: zzak &lt;zzak@hey.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Simplify Set#inspect output</title>
<updated>2025-06-25T00:21:07+00:00</updated>
<author>
<name>Jeremy Evans</name>
<email>code@jeremyevans.net</email>
</author>
<published>2025-05-31T00:55:05+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=3a9c091cf393e8a9c4e4b93d4216f2be3678e488'/>
<id>3a9c091cf393e8a9c4e4b93d4216f2be3678e488</id>
<content type='text'>
As Set is now a core collection class, it should have special inspect
output.  Ideally, inspect output should be suitable to eval, similar
to array and hash (assuming the elements are also suitable to eval):

  set = Set[1, 2, 3]
  eval(set.inspect) == set # should be true

The simplest way to do this is to use the Set[] syntax.

This deliberately does not use any subclass name in the output,
similar to array and hash. It is more important that users know they
are dealing with a set than which subclass:

  Class.new(Set)[]
  # this does: Set[]
  # not: #&lt;Class:0x00000c21c78699e0&gt;[]

This inspect change breaks the power_assert bundled gem tests, so
add power_assert to TEST_BUNDLED_GEMS_ALLOW_FAILURES in the workflows.

Implements [Feature #21389]
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
As Set is now a core collection class, it should have special inspect
output.  Ideally, inspect output should be suitable to eval, similar
to array and hash (assuming the elements are also suitable to eval):

  set = Set[1, 2, 3]
  eval(set.inspect) == set # should be true

The simplest way to do this is to use the Set[] syntax.

This deliberately does not use any subclass name in the output,
similar to array and hash. It is more important that users know they
are dealing with a set than which subclass:

  Class.new(Set)[]
  # this does: Set[]
  # not: #&lt;Class:0x00000c21c78699e0&gt;[]

This inspect change breaks the power_assert bundled gem tests, so
add power_assert to TEST_BUNDLED_GEMS_ALLOW_FAILURES in the workflows.

Implements [Feature #21389]
</pre>
</div>
</content>
</entry>
<entry>
<title>[Bug #21449] Fix Set#divide{|a,b|} using Union-find structure (#13680)</title>
<updated>2025-06-23T17:56:04+00:00</updated>
<author>
<name>tomoya ishida</name>
<email>tomoyapenguin@gmail.com</email>
</author>
<published>2025-06-23T17:56:04+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=67346a7d94b101acc00c177b01ad0aabfef605a8'/>
<id>67346a7d94b101acc00c177b01ad0aabfef605a8</id>
<content type='text'>
* [Bug #21449] Fix Set#divide{|a,b|} using Union-find structure

Implements Union-find structure with path compression.
Since divide{|a,b|} calls the given block n**2 times in the worst case, there is no need to implement union-by-rank or union-by-size optimization.

* Avoid internal arrays from being modified from block passed to Set#divide

Internal arrays can be modified from yielded block through ObjectSpace.
Freeze readonly array, use ALLOCV_N instead of mutable array.</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
* [Bug #21449] Fix Set#divide{|a,b|} using Union-find structure

Implements Union-find structure with path compression.
Since divide{|a,b|} calls the given block n**2 times in the worst case, there is no need to implement union-by-rank or union-by-size optimization.

* Avoid internal arrays from being modified from block passed to Set#divide

Internal arrays can be modified from yielded block through ObjectSpace.
Freeze readonly array, use ALLOCV_N instead of mutable array.</pre>
</div>
</content>
</entry>
</feed>
