summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2019-08-07 09:01:33 -0700
committerJeremy Evans <code@jeremyevans.net>2019-09-21 16:10:37 -0700
commit2e551356a7a6e74ba07283e000ff16f5d1ea6506 (patch)
tree99c123bb12c43346d9b1748cd73c42b883c6bb0a
parent7470f965650bf17875632f0c5f9e5a4d9de9fc3f (diff)
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]
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/2473
-rw-r--r--complex.c3
-rw-r--r--ext/bigdecimal/bigdecimal.c3
-rw-r--r--ext/pathname/pathname.c2
-rw-r--r--test/bigdecimal/test_bigdecimal.rb5
-rw-r--r--test/pathname/test_pathname.rb6
-rw-r--r--test/ruby/test_complex.rb4
6 files changed, 23 insertions, 0 deletions
diff --git a/complex.c b/complex.c
index ec60c00ed6..144a59d533 100644
--- a/complex.c
+++ b/complex.c
@@ -563,6 +563,9 @@ nucomp_f_complex(int argc, VALUE *argv, VALUE klass)
if (!NIL_P(opts)) {
raise = rb_opts_exception_p(opts, raise);
}
+ if (argc > 0 && CLASS_OF(a1) == rb_cComplex && a2 == Qundef) {
+ return a1;
+ }
return nucomp_convert(rb_cComplex, a1, a2, raise);
}
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index 652f341fb9..6d5047553b 100644
--- a/ext/bigdecimal/bigdecimal.c
+++ b/ext/bigdecimal/bigdecimal.c
@@ -2722,6 +2722,9 @@ f_BigDecimal(int argc, VALUE *argv, VALUE self)
Real *pv;
VALUE obj;
+ if (argc > 0 && CLASS_OF(argv[0]) == rb_cBigDecimal) {
+ if (argc == 1 || (argc == 2 && RB_TYPE_P(argv[1], T_HASH))) 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..b3368b4f4b 100644
--- a/test/bigdecimal/test_bigdecimal.rb
+++ b/test/bigdecimal/test_bigdecimal.rb
@@ -54,6 +54,11 @@ class TestBigDecimal < Test::Unit::TestCase
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.12", 1)
+ assert_same(bd, BigDecimal(bd))
+ assert_same(bd, BigDecimal(bd, exception: false))
+ assert_not_same(bd, BigDecimal(bd, 1))
+ assert_not_same(bd, BigDecimal(bd, 1, exception: false))
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 eaecc52475..af523f9f98 100644
--- a/test/pathname/test_pathname.rb
+++ b/test/pathname/test_pathname.rb
@@ -471,6 +471,12 @@ class TestPathname < Test::Unit::TestCase
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..a4fe9d4232 100644
--- a/test/ruby/test_complex.rb
+++ b/test/ruby/test_complex.rb
@@ -123,6 +123,10 @@ class Complex_Test < Test::Unit::TestCase
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))
+ assert_same(c, Complex(c, exception: false))
+ assert_raise(ArgumentError){Complex(c, bad_keyword: true)}
if (0.0/0).nan?
assert_nothing_raised{Complex(0.0/0)}