Issue #12979 has been updated by Nobuyoshi Nakada.


I found that a rubygems test ,`TestGemSpecification#test_initialize_copy_broken` in test/rubygems/test_gem_specification.rb, depends on this exception.
And rubyspec fails as usual.

```diff
diff --git i/object.c w/object.c
index 05bef4d..7075e13 100644
--- i/object.c
+++ w/object.c
@@ -423,7 +423,7 @@ rb_obj_dup(VALUE obj)
     VALUE dup;
 
     if (rb_special_const_p(obj)) {
-        rb_raise(rb_eTypeError, "can't dup %s", rb_obj_classname(obj));
+	return obj;
     }
     dup = rb_obj_alloc(rb_obj_class(obj));
     init_copy(dup, obj);
diff --git i/test/ruby/test_object.rb w/test/ruby/test_object.rb
index 7b3defa..2f80bc6 100644
--- i/test/ruby/test_object.rb
+++ w/test/ruby/test_object.rb
@@ -19,9 +19,9 @@
   end
 
   def test_dup
-    assert_raise(TypeError) { 1.dup }
-    assert_raise(TypeError) { true.dup }
-    assert_raise(TypeError) { nil.dup }
+    assert_equal 1, 1.dup
+    assert_equal true, true.dup
+    assert_equal nil, nil.dup
 
     assert_raise(TypeError) do
       Object.new.instance_eval { initialize_copy(1) }
diff --git i/test/rubygems/test_gem_specification.rb w/test/rubygems/test_gem_specification.rb
index 87f0f36..0d51d93 100644
--- i/test/rubygems/test_gem_specification.rb
+++ w/test/rubygems/test_gem_specification.rb
@@ -1260,7 +1260,8 @@
       s.version = '1'
     end
 
-    spec.instance_variable_set :@licenses, :blah
+    def (broken_license = Object.new).dup; raise TypeError; end
+    spec.instance_variable_set :@licenses, broken_license
     spec.loaded_from = '/path/to/file'
 
     e = assert_raises Gem::FormatException do
```

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

* Author: Martin Drst
* Status: Open
* Priority: Normal
* Assignee: Nobuyoshi Nakada
----------------------------------------
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>