Issue #12979 has been updated by Mike Vastola.


Sorry.. I'm not used to Redmine and I was confused because there was no conclusion to the discussion about the **`ArgumentError`**. 

I understand that Casper's request should be a separate issue (I'll leave him to submit that since I trust he can argue it better than I.) but I think  the raising of an **`ArgumentError`** constitutes a bug in this fix (I guess it's technically a regression if we're calling this a fix) and warrants further discussion. Given that it concerns the people active on this issue, should it still be discussed in a separate issue?

If necessary, I'll copy the following into a separate issue, but...

**`ArgumentError#message`** is **`"can't unfreeze %s"`**, but the [inline documentation](https://github.com/ruby/ruby/blob/7f30d00b53bd5ce680c13f3bcd57e8e29039aaee/object.c#L317-L321) for **`Object#clone`** doesn't state that setting the **`:freeze`** key of the option **`Hash`** to **`false`** affirmatively causes anything to happen at all. Quite the opposite, in fact. It states that the frozen state is copied if (and only if) the **`:freeze`** option is either **`nil`** or **`true`**. 

If **`Object#clone`** is called with the **`:freeze`** key of the option **`Hash`** set to **`false`**, intuitively, the method should behave identically to **`Object#dup`**. In other words, there should be no error triggered. The only difference *would* be (as is documented) in the case of descendant classes, but since the classes of these special constants are themselves immutable (and don't have singletons), there is no way to create a descendant class for those.

I understand the theory behind doing this: people who already have this code in place may (depending on usage) expect all objects produced by it to be freely mutable. IMHO, however, this is short-sighted. This prioritizes backwards-compatibility over continuity and intuitiveness. If this is truly a concern, I think printing a warning rather than raising an error might be a sensitive alternative.

We shouldn't look at this simply in terms of the use cases of this code currently in the wild now, however. Once this feature is widely available, it's possible people will still want to use **`Object#clone`** with **`:freeze`** set to **`false`** (due to it's different handling of descendant classes for objects that are thusly altered) while silently passing through immediates.

----------------------------------------
Feature #12979: Avoid exception for #dup on Integer (and similar cases)
https://bugs.ruby-lang.org/issues/12979#change-62223

* Author: Martin Drst
* Status: Closed
* Priority: Normal
* Assignee: Nobuyoshi Nakada
* Target version: 
----------------------------------------
This is a proposal resulting from a discussion in Bug #11929. Because this is proposing a different solution from #11929, it has a new number.

#11929 shows that people are confused that e.g. 3.dup throws an exception (but Integer#dup is actually implemented, so Integer.respond_to? :dup => true).

Integer#dup should fail silently, returning the receiver, in the same way as Integer#freeze fails silently. Citing from #11929 (comment by Mike Vastola): "If the object can't be duped/cloned because it's an immediate, dup/clone should return the object itself. (There shouldn't be any harm in doing so since nothing about the object can be changed in the first place.)". Citing some more:

> I literally can't imagine any scenario in which a dev, when, say, coding a class with the line:
> 
> return val.dup.freeze
> .. really wants an Exception thrown when val happens to be de-facto un-dup-able. What they really want is:
> 
> return val.dup.freeze rescue val

The proposal also has the advantage that it leads to a much more unified, streamlined protocol, avoiding needless exposition of internals. It would do exactly what dup (and clone) are described to do, namely (pretend to) return a shallow copy.



-- 
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>