[ruby-core:122695] [Ruby Bug#21396] Set#initialize should call Set#add on items passed in
From:
"Eregon (Benoit Daloze) via ruby-core" <ruby-core@...>
Date:
2025-07-09 08:12:11 UTC
List:
ruby-core #122695
Issue #21396 has been updated by Eregon (Benoit Daloze).
Regarding thread-safety, for `add?` the only thing is the return value where the old implementation might potentially return the Set even though the element was added concurrently.
It's still thread-safe in that it doesn't corrupt the Set or anything like that, and the given element is always added to the Set when the method returns.
> Since there were not explicit tests that methods should call other methods
There were a few ruby/spec specs which you disabled in https://github.com/ruby/ruby/pull/13074/files#diff-00365d65577dd7b3e357e99b895bb8e5a26d699c33a1afabc1a48cd91a8c5914
Those specs or at least part of those specs were added in https://github.com/ruby/spec/pull/629 to ensure proper interop with Set-like classes, as tested with SetSpecs::SetLike and used e.g. in the persistent-dmnd gem.
https://bugs.ruby-lang.org/issues/15240 is the related issue to make this kind of interop better defined and less hacky.
Probably interop with Set-like classes not inheriting from Set is too much of a ask, but it might be good to re-enable these specs and change `SetSpecs::SetLike` to inherit from `Set`.
----------------------------------------
Bug #21396: Set#initialize should call Set#add on items passed in
https://bugs.ruby-lang.org/issues/21396#change-113973
* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN
----------------------------------------
```ruby
class Foo < Set
def add(item) = super(item.bytesize)
end
x = Foo.new(["foo"])
p x
p x.include?(3)
```
On Ruby 3.4 the output is this:
```
> ruby -v test.rb
ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +PRISM [arm64-darwin24]
#<Foo: {3}>
true
```
On Ruby master the output is this:
```
> make run
./miniruby -I./lib -I. -I.ext/common -r./arm64-darwin24-fake ./test.rb
#<Set: {"foo"}>
false
```
The bug is that `initialize` is not calling `add` for the elements passed in, so the subclass doesn't get a chance to change them.
I've sent a PR here: https://github.com/ruby/ruby/pull/13518
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/