* [ruby-core:122303] [Ruby Bug#21375] Set[] does not call #initialize
@ 2025-05-27 5:30 Ethan (Ethan -) via ruby-core
2025-05-27 6:09 ` [ruby-core:122304] " nobu (Nobuyoshi Nakada) via ruby-core
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Ethan (Ethan -) via ruby-core @ 2025-05-27 5:30 UTC (permalink / raw)
To: ruby-core; +Cc: Ethan (Ethan -)
Issue #21375 has been reported by Ethan (Ethan -).
----------------------------------------
Bug #21375: Set[] does not call #initialize
https://bugs.ruby-lang.org/issues/21375
* Author: Ethan (Ethan -)
* Status: Open
* ruby -v: ruby 3.5.0dev (2025-05-26T17:42:35Z master 909a0daab6) +PRISM [x86_64-darwin22]
* Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN
----------------------------------------
I have a subclass of Set that overrides #initialize. Following #21216, .new does call #initialize but .[] does not.
```ruby
class MySet < Set
def initialize(enum = nil)
compare_by_identity
super
end
end
MySet.new.compare_by_identity?
# => true
MySet[].compare_by_identity?
# => false
```
--
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/
^ permalink raw reply [flat|nested] 6+ messages in thread
* [ruby-core:122304] [Ruby Bug#21375] Set[] does not call #initialize
2025-05-27 5:30 [ruby-core:122303] [Ruby Bug#21375] Set[] does not call #initialize Ethan (Ethan -) via ruby-core
@ 2025-05-27 6:09 ` nobu (Nobuyoshi Nakada) via ruby-core
2025-05-27 14:43 ` [ruby-core:122311] " jeremyevans0 (Jeremy Evans) via ruby-core
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: nobu (Nobuyoshi Nakada) via ruby-core @ 2025-05-27 6:09 UTC (permalink / raw)
To: ruby-core; +Cc: nobu (Nobuyoshi Nakada)
Issue #21375 has been updated by nobu (Nobuyoshi Nakada).
I'm not sure if it is intentional or not.
If unintentional, this patch may fix it.
```diff
diff --git a/set.c b/set.c
index 8676c62cd35..c41781c446f 100644
--- a/set.c
+++ b/set.c
@@ -409,13 +409,7 @@ static VALUE
set_s_create(int argc, VALUE *argv, VALUE klass)
{
VALUE set = set_alloc_with_size(klass, argc);
- set_table *table = RSET_TABLE(set);
- int i;
-
- for (i=0; i < argc; i++) {
- set_table_insert_wb(table, set, argv[i], NULL);
- }
-
+ rb_obj_call_init(set, argc, argv);
return set;
}
```
----------------------------------------
Bug #21375: Set[] does not call #initialize
https://bugs.ruby-lang.org/issues/21375#change-113447
* Author: Ethan (Ethan -)
* Status: Open
* ruby -v: ruby 3.5.0dev (2025-05-26T17:42:35Z master 909a0daab6) +PRISM [x86_64-darwin22]
* Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN
----------------------------------------
I have a subclass of Set that overrides #initialize. Following #21216, .new does call #initialize but .[] does not.
```ruby
class MySet < Set
def initialize(enum = nil)
compare_by_identity
super
end
end
MySet.new.compare_by_identity?
# => true
MySet[].compare_by_identity?
# => false
```
--
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/
^ permalink raw reply [flat|nested] 6+ messages in thread
* [ruby-core:122311] [Ruby Bug#21375] Set[] does not call #initialize
2025-05-27 5:30 [ruby-core:122303] [Ruby Bug#21375] Set[] does not call #initialize Ethan (Ethan -) via ruby-core
2025-05-27 6:09 ` [ruby-core:122304] " nobu (Nobuyoshi Nakada) via ruby-core
@ 2025-05-27 14:43 ` jeremyevans0 (Jeremy Evans) via ruby-core
2025-05-28 3:56 ` [ruby-core:122319] " Ethan (Ethan -) via ruby-core
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: jeremyevans0 (Jeremy Evans) via ruby-core @ 2025-05-27 14:43 UTC (permalink / raw)
To: ruby-core; +Cc: jeremyevans0 (Jeremy Evans)
Issue #21375 has been updated by jeremyevans0 (Jeremy Evans).
nobu (Nobuyoshi Nakada) wrote in #note-1:
> I'm not sure if it is intentional or not.
It was intentional when I developed core Set. `Set.[]` takes different arguments than `Set#initialize`.
`Array.[]` does not call `Array#initialize`, and `Hash.[]` does not call `Hash#initialize`, so there is precedent for the core collection classes to operate this way.
`Set.[]` was not documented as calling `Set#initialize` previously, and there were no tests or specs for it. Relying on `Set.[]` calling `Set#initialize` was relying on undefined behavior.
> If unintentional, this patch may fix it.
>
> ```diff
> diff --git a/set.c b/set.c
> index 8676c62cd35..c41781c446f 100644
> --- a/set.c
> +++ b/set.c
> @@ -409,13 +409,7 @@ static VALUE
> set_s_create(int argc, VALUE *argv, VALUE klass)
> {
> VALUE set = set_alloc_with_size(klass, argc);
> - set_table *table = RSET_TABLE(set);
> - int i;
> -
> - for (i=0; i < argc; i++) {
> - set_table_insert_wb(table, set, argv[i], NULL);
> - }
> -
> + rb_obj_call_init(set, argc, argv);
> return set;
> }
>
> ```
I'm not sure whether this is correct. `#initialize` arguments are enumerables of elements, `.[]` arguments are elements. I think if we wanted to call `#initialize`, we would have to allocate an array for the elements, and pass that, which would reduce performance.
----------------------------------------
Bug #21375: Set[] does not call #initialize
https://bugs.ruby-lang.org/issues/21375#change-113453
* Author: Ethan (Ethan -)
* Status: Open
* ruby -v: ruby 3.5.0dev (2025-05-26T17:42:35Z master 909a0daab6) +PRISM [x86_64-darwin22]
* Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN
----------------------------------------
I have a subclass of Set that overrides #initialize. Following #21216, .new does call #initialize but .[] does not.
```ruby
class MySet < Set
def initialize(enum = nil)
compare_by_identity
super
end
end
MySet.new.compare_by_identity?
# => true
MySet[].compare_by_identity?
# => false
```
--
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/
^ permalink raw reply [flat|nested] 6+ messages in thread
* [ruby-core:122319] [Ruby Bug#21375] Set[] does not call #initialize
2025-05-27 5:30 [ruby-core:122303] [Ruby Bug#21375] Set[] does not call #initialize Ethan (Ethan -) via ruby-core
2025-05-27 6:09 ` [ruby-core:122304] " nobu (Nobuyoshi Nakada) via ruby-core
2025-05-27 14:43 ` [ruby-core:122311] " jeremyevans0 (Jeremy Evans) via ruby-core
@ 2025-05-28 3:56 ` Ethan (Ethan -) via ruby-core
2025-06-01 20:03 ` [ruby-core:122364] " Eregon (Benoit Daloze) via ruby-core
2025-06-20 17:37 ` [ruby-core:122564] " Dan0042 (Daniel DeLorme) via ruby-core
4 siblings, 0 replies; 6+ messages in thread
From: Ethan (Ethan -) via ruby-core @ 2025-05-28 3:56 UTC (permalink / raw)
To: ruby-core; +Cc: Ethan (Ethan -)
Issue #21375 has been updated by Ethan (Ethan -).
It seems like a regression to me. I mean, it broke my code - maybe I'm alone, I can't say whether other people override #initialize and expect Set[] to call it, but it seems like a reasonable assumption to make, particularly since it always has done that. I wasn't aware that Array[]/Hash[] don't call initialize and I find that counterintuitive, and would advocate against changing other classes/constructors to do that.
> `Set.[]` was not documented as calling `Set#initialize` previously
My feeling is that the base expectation is that #initialize is called on new objects. I know constructors can allocate and do things without #initialize, but I think that is quite rare. Maybe I'm wrong, I just learned Array[] and Hash[] do that, but I've almost never seen it.
I'll also note that the effects of not calling #initialize are easy to miss, since the set will still be a perfectly functional set, but will have lost whatever checks or changes are intended on initialization. At least in my case this was not straightforward to trace back to this change, it took me a while in the debugger to figure out that some of my sets were unexpectedly no longer compare_by_identity as my #initialize sets.
Having figured that out it is of course trivial for me to override MySet.[], but I'd rather Set behave like it used to, especially if that would save other people having to debug subtle bugs and fix.
----------------------------------------
Bug #21375: Set[] does not call #initialize
https://bugs.ruby-lang.org/issues/21375#change-113460
* Author: Ethan (Ethan -)
* Status: Open
* ruby -v: ruby 3.5.0dev (2025-05-26T17:42:35Z master 909a0daab6) +PRISM [x86_64-darwin22]
* Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN
----------------------------------------
I have a subclass of Set that overrides #initialize. Following #21216, .new does call #initialize but .[] does not.
```ruby
class MySet < Set
def initialize(enum = nil)
compare_by_identity
super
end
end
MySet.new.compare_by_identity?
# => true
MySet[].compare_by_identity?
# => false
```
--
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/
^ permalink raw reply [flat|nested] 6+ messages in thread
* [ruby-core:122364] [Ruby Bug#21375] Set[] does not call #initialize
2025-05-27 5:30 [ruby-core:122303] [Ruby Bug#21375] Set[] does not call #initialize Ethan (Ethan -) via ruby-core
` (2 preceding siblings ...)
2025-05-28 3:56 ` [ruby-core:122319] " Ethan (Ethan -) via ruby-core
@ 2025-06-01 20:03 ` Eregon (Benoit Daloze) via ruby-core
2025-06-20 17:37 ` [ruby-core:122564] " Dan0042 (Daniel DeLorme) via ruby-core
4 siblings, 0 replies; 6+ messages in thread
From: Eregon (Benoit Daloze) via ruby-core @ 2025-06-01 20:03 UTC (permalink / raw)
To: ruby-core; +Cc: Eregon (Benoit Daloze)
Issue #21375 has been updated by Eregon (Benoit Daloze).
IMO this is unnecessarily breaking compatibility.
If we don't want to support subclasses of Set properly as it used to work (and calling `initialize` is I think a totally reasonable assumption, especially for any library which used to be written in Ruby), then I think we should forbid subclassing Set entirely to make it clear.
----------------------------------------
Bug #21375: Set[] does not call #initialize
https://bugs.ruby-lang.org/issues/21375#change-113509
* Author: Ethan (Ethan -)
* Status: Open
* ruby -v: ruby 3.5.0dev (2025-05-26T17:42:35Z master 909a0daab6) +PRISM [x86_64-darwin22]
* Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN
----------------------------------------
I have a subclass of Set that overrides #initialize. Following #21216, .new does call #initialize but .[] does not.
```ruby
class MySet < Set
def initialize(enum = nil)
compare_by_identity
super
end
end
MySet.new.compare_by_identity?
# => true
MySet[].compare_by_identity?
# => false
```
--
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/
^ permalink raw reply [flat|nested] 6+ messages in thread
* [ruby-core:122564] [Ruby Bug#21375] Set[] does not call #initialize
2025-05-27 5:30 [ruby-core:122303] [Ruby Bug#21375] Set[] does not call #initialize Ethan (Ethan -) via ruby-core
` (3 preceding siblings ...)
2025-06-01 20:03 ` [ruby-core:122364] " Eregon (Benoit Daloze) via ruby-core
@ 2025-06-20 17:37 ` Dan0042 (Daniel DeLorme) via ruby-core
4 siblings, 0 replies; 6+ messages in thread
From: Dan0042 (Daniel DeLorme) via ruby-core @ 2025-06-20 17:37 UTC (permalink / raw)
To: ruby-core; +Cc: Dan0042 (Daniel DeLorme)
Issue #21375 has been updated by Dan0042 (Daniel DeLorme).
Ethan (Ethan -) wrote in #note-3:
> My feeling is that the base expectation is that #initialize is called on new objects.
I agree.
`Array[*args]` is equivalent to `Array.new.concat(*args)` and in that case there was no need to call #initialize because it's a no-op when there are no arguments. But the side-effect of that optimization is that `MyArray[*args]` does not call #initialize when it should, and I consider that a bug. It would be better to fix that bug in `Array` rather than introduce it in `Set` just to keep things "consistent".
----------------------------------------
Bug #21375: Set[] does not call #initialize
https://bugs.ruby-lang.org/issues/21375#change-113794
* Author: Ethan (Ethan -)
* Status: Open
* ruby -v: ruby 3.5.0dev (2025-05-26T17:42:35Z master 909a0daab6) +PRISM [x86_64-darwin22]
* Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN
----------------------------------------
I have a subclass of Set that overrides #initialize. Following #21216, .new does call #initialize but .[] does not.
```ruby
class MySet < Set
def initialize(enum = nil)
compare_by_identity
super
end
end
MySet.new.compare_by_identity?
# => true
MySet[].compare_by_identity?
# => false
```
--
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/
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-06-20 17:38 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-05-27 5:30 [ruby-core:122303] [Ruby Bug#21375] Set[] does not call #initialize Ethan (Ethan -) via ruby-core
2025-05-27 6:09 ` [ruby-core:122304] " nobu (Nobuyoshi Nakada) via ruby-core
2025-05-27 14:43 ` [ruby-core:122311] " jeremyevans0 (Jeremy Evans) via ruby-core
2025-05-28 3:56 ` [ruby-core:122319] " Ethan (Ethan -) via ruby-core
2025-06-01 20:03 ` [ruby-core:122364] " Eregon (Benoit Daloze) via ruby-core
2025-06-20 17:37 ` [ruby-core:122564] " Dan0042 (Daniel DeLorme) via ruby-core
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).