
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/