From: "matz (Yukihiro Matsumoto) via ruby-core" <ruby-core@...>
Date: 2023-06-08T09:42:20+00:00
Subject: [ruby-core:113820] [Ruby master Feature#19712] IO#reopen removes singleton class

Issue #19712 has been updated by matz (Yukihiro Matsumoto).


We still have concerns about compatibility.

One is keeping the receiver's class, and the other is mixing of file descriptors and sockets (especially on Windows).
Both can be the cause of issues that cannot be solved easily.

We have discussed some possible solutions, for example:

* use dup2 instead of copying the IO object (may not work with sockets)
* prohibit `#reopen` if the replacement's class does not have direct inheritance relationship  (may prohibit current working programs)

But none of them are free from compatibility issues.

I don't think it's worth the incompatibility and additional complexity.

Matz.


----------------------------------------
Feature #19712: IO#reopen removes singleton class
https://bugs.ruby-lang.org/issues/19712#change-103467

* Author: itarato (Peter Arato)
* Status: Open
* Priority: Normal
----------------------------------------
The documentation states:

> This may dynamically change the actual class of this stream.

As well `#reopen` removes the singleton class, even when the logical class is the same. This can be surprising at times.

An example:

``` ruby
io = File.open(__FILE__)
io.define_singleton_method(:foo) {}
io.reopen(File.open(__FILE__))
io.foo # `<main>': undefined method `foo' for #<File:/test.rb> (NoMethodError)
```

An example where this was an issue: https://github.com/oracle/truffleruby/pull/3088 Tl;dr: a popular gem was enhancing the singleton class of STDOUT, while Rails/ActiveSupport was executing an `IO#reopen` - invalidating the changes by the gem.

While it's hard to trivially solve this with keeping the intended functionality, could it be considered to make edge cases more visible?

Examples:
- `IO#reopen` issues a warning message when the receiver's singleton class has been updated (but keep removing it as of current state)
- `IO#reopen` is limited on instances with a default singleton class, and issues an error when called on an instance with an updated singleton class
- make `IO#reopen` carry over the singleton class *only* if the recipient and argument's class are the same, and yield an error otherwise (different classes)

These are just ideas. I'm more looking for feedback from the core devs at this point. Thanks in advance!



-- 
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/postorius/lists/ruby-core.ml.ruby-lang.org/