Issue #15027 has been updated by mame (Yusuke Endoh).


In general, optimization should be invisible from users (except performance).  This kind of redefinition checks in VM are carefully designed to be invisible.

Apparently, `Struct#select` is defined for the sake of performance improvement.  But IMO, it is not an optimization because it is still visible from users, even after this hack is introduced.

```
class Foo < Struct.new(:bar)
end

class Bar
  include Enumerable
end

Bar.instance_method(:select).bind_call([:ok]) {|x| p x } #=> :ok
Foo.instance_method(:select).bind_call([:ok]) {|x| p x }
  #=> bind argument must be an instance of Struct (TypeError)
```

If there is no redefinition check, we can easily explain the current situation; it is a normal override.

That being said, I agree that the current behavior looks inconsistent.  I don't like the patch, but I'm not against it.

----------------------------------------
Bug #15027: When Struct#each method is overriden Struct#select and Struct#to_a use wrong collections
https://bugs.ruby-lang.org/issues/15027#change-83054

* Author: bruno (Bruno Sutic)
* Status: Assigned
* Priority: Normal
* Assignee: matz (Yukihiro Matsumoto)
* Target version: 
* ruby -v: 2.6.0dev
* Backport: 2.3: UNKNOWN, 2.4: UNKNOWN, 2.5: UNKNOWN
----------------------------------------
### Bug

Here's the code snippet that should reproduce the problem:

~~~ ruby
class Foo < Struct.new(:bar)
  def each(&block)
    [:baz, :qux].each(&block)
  end
end

foo = Foo.new(:foo)
foo.map(&:itself) # => [:baz, :qux]  # OK

foo.to_a # => [:foo]  # NOT OK, expected [:baz, :qux]
foo.select(&:itself) # => [:foo]  # NOT OK, expected [:baz, :qux]
~~~

As you can see, even tho we defined another collection for use by overriding `#each`, the `to_a` and `select` still use `Struct`'s original collection.

The problem seem to be with `Struct#to_a` and `Struct#select` methods from `struct.c` file that are defined unnecessarily.

### Proposed solution

The attached solution simply deletes `Struct#select` and `Struct#to_a`. A couple tests are added to show everything still works as before.

Please let me know if I can provide any more info and I'll be ready to do so.

---Files--------------------------------
struct_enumerable_fix.patch (2.8 KB)
struct_enumerable_fix2.patch (1.51 KB)


-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>