From 568a98fc072c88efc7b68c5cf52796671ae71eb5 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Wed, 7 Aug 2019 09:01:33 -0700 Subject: [PATCH] Make Kernel#{Pathname,BigDecimal,Complex} return argument if given correct type This is how Kernel#{Array,String,Float,Integer,Hash,Rational} work. BigDecimal and Complex instances are always frozen, so this should not cause backwards compatibility issues for those. Pathname instances are not frozen, so potentially this could cause backwards compatibility issues by not returning a new object. Based on a patch from Joshua Ballanco, some minor changes by me. Fixes [Bug #7522] --- complex.c | 2 ++ ext/bigdecimal/bigdecimal.c | 1 + ext/pathname/pathname.c | 2 ++ test/bigdecimal/test_bigdecimal.rb | 2 ++ test/pathname/test_pathname.rb | 6 ++++++ test/ruby/test_complex.rb | 2 ++ 6 files changed, 15 insertions(+) diff --git a/complex.c b/complex.c index 4c51d1a2d6..73144355da 100644 --- a/complex.c +++ b/complex.c @@ -531,6 +531,8 @@ nucomp_f_complex(int argc, VALUE *argv, VALUE klass) } if (!NIL_P(opts)) { raise = rb_opts_exception_p(opts, raise); + } else if (argc == 1 && CLASS_OF(a1) == rb_cComplex) { + return a1; } return nucomp_convert(rb_cComplex, a1, a2, raise); } diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c index 652f341fb9..6d3bf0fa4e 100644 --- a/ext/bigdecimal/bigdecimal.c +++ b/ext/bigdecimal/bigdecimal.c @@ -2722,6 +2722,7 @@ f_BigDecimal(int argc, VALUE *argv, VALUE self) Real *pv; VALUE obj; + if (argc == 1 && CLASS_OF(argv[0]) == rb_cBigDecimal) return argv[0]; obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0); pv = BigDecimal_new(argc, argv); if (pv == NULL) return Qnil; diff --git a/ext/pathname/pathname.c b/ext/pathname/pathname.c index 70f82583a1..1cf0f90b9f 100644 --- a/ext/pathname/pathname.c +++ b/ext/pathname/pathname.c @@ -1323,6 +1323,8 @@ path_unlink(VALUE self) static VALUE path_f_pathname(VALUE self, VALUE str) { + if (CLASS_OF(str) == rb_cPathname) + return str; return rb_class_new_instance(1, &str, rb_cPathname); } diff --git a/test/bigdecimal/test_bigdecimal.rb b/test/bigdecimal/test_bigdecimal.rb index e4f14449a1..f59c9ec43e 100644 --- a/test/bigdecimal/test_bigdecimal.rb +++ b/test/bigdecimal/test_bigdecimal.rb @@ -54,6 +54,8 @@ def test_BigDecimal assert_equal(111, BigDecimal("1_1_1_")) assert_equal(10**(-1), BigDecimal("1E-1"), '#4825') assert_equal(1234, BigDecimal(" \t\n\r \r1234 \t\n\r \r")) + bd = BigDecimal.new("1", 1) + assert_same(bd, BigDecimal(bd)) assert_raise(ArgumentError) { BigDecimal("1", -1) } assert_raise_with_message(ArgumentError, /"1__1_1"/) { BigDecimal("1__1_1") } diff --git a/test/pathname/test_pathname.rb b/test/pathname/test_pathname.rb index 076a73e50b..061ae3e1e4 100644 --- a/test/pathname/test_pathname.rb +++ b/test/pathname/test_pathname.rb @@ -471,6 +471,12 @@ def test_initialize_nul assert_raise(ArgumentError) { Pathname.new("a\0") } end + def test_global_constructor + p = Pathname.new('a') + assert_equal(p, Pathname('a')) + assert_same(p, Pathname(p)) + end + class AnotherStringLike # :nodoc: def initialize(s) @s = s end def to_str() @s end diff --git a/test/ruby/test_complex.rb b/test/ruby/test_complex.rb index 2a72f3bcb9..f4d9ec0e7f 100644 --- a/test/ruby/test_complex.rb +++ b/test/ruby/test_complex.rb @@ -123,6 +123,8 @@ def test_conv assert_raise(TypeError){Complex(Object.new)} assert_raise(ArgumentError){Complex()} assert_raise(ArgumentError){Complex(1,2,3)} + c = Complex(1,0) + assert_same(c, Complex(c)) if (0.0/0).nan? assert_nothing_raised{Complex(0.0/0)} -- 2.21.0