summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-12-21 12:06:40 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-12-21 12:06:40 +0000
commit5518b5c21a2168e45aa2382344583178cbb83c13 (patch)
tree33d64e7b7cca126039bca7085eed290d2da8b31b
parent33e8eef020018693e93e5df85655a8e8e0042d69 (diff)
time.c: refine num_exact error message
* time.c (num_exact): show the original argument when conversion failed, instead of intermediate nil. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57140 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--test/ruby/test_time.rb10
-rw-r--r--time.c55
2 files changed, 34 insertions, 31 deletions
diff --git a/test/ruby/test_time.rb b/test/ruby/test_time.rb
index 60bed87c9c..d3a8645024 100644
--- a/test/ruby/test_time.rb
+++ b/test/ruby/test_time.rb
@@ -1089,4 +1089,14 @@ class TestTime < Test::Unit::TestCase
t = Time.utc(2017, 1, 1, 1, 0, 0).getlocal("-05:00")
assert_equal("366", t.strftime("%j"))
end
+
+ def test_num_exact_error
+ bad = EnvUtil.labeled_class("BadValue").new
+ x = EnvUtil.labeled_class("Inexact") do
+ def to_s; "Inexact"; end
+ define_method(:to_int) {bad}
+ define_method(:to_r) {bad}
+ end.new
+ assert_raise_with_message(TypeError, /Inexact/) {Time.at(x)}
+ end
end
diff --git a/time.c b/time.c
index e3c1426b57..a99444fce1 100644
--- a/time.c
+++ b/time.c
@@ -482,51 +482,44 @@ static VALUE
num_exact(VALUE v)
{
VALUE tmp;
- int t;
- t = TYPE(v);
- switch (t) {
- case T_FIXNUM:
- case T_BIGNUM:
+ if (NIL_P(v)) {
+ rb_raise(rb_eTypeError, "can't convert nil into an exact number");
+ }
+ else if (RB_INTEGER_TYPE_P(v)) {
return v;
-
- case T_RATIONAL:
- break;
-
- case T_STRING:
- case T_NIL:
+ }
+ else if (RB_TYPE_P(v, T_RATIONAL)) {
+ goto rational;
+ }
+ else if (RB_TYPE_P(v, T_STRING)) {
goto typeerror;
-
- default:
+ }
+ else {
if ((tmp = rb_check_funcall(v, rb_intern("to_r"), 0, NULL)) != Qundef) {
/* test to_int method availability to reject non-Numeric
* objects such as String, Time, etc which have to_r method. */
if (!rb_respond_to(v, rb_intern("to_int"))) goto typeerror;
- v = tmp;
- break;
}
- if (!NIL_P(tmp = rb_check_to_integer(v, "to_int"))) {
- v = tmp;
- break;
+ else if (!NIL_P(tmp = rb_check_to_int(v))) {
+ return tmp;
+ }
+ else {
+ goto typeerror;
}
- goto typeerror;
}
- t = TYPE(v);
- switch (t) {
- case T_FIXNUM:
- case T_BIGNUM:
- return v;
-
- case T_RATIONAL:
+ if (RB_INTEGER_TYPE_P(tmp)) {
+ v = tmp;
+ }
+ else if (RB_TYPE_P(tmp, T_RATIONAL)) {
+ v = tmp;
+ rational:
if (RRATIONAL(v)->den == INT2FIX(1))
v = RRATIONAL(v)->num;
- break;
-
- default:
+ }
+ else {
typeerror:
- if (NIL_P(v))
- rb_raise(rb_eTypeError, "can't convert nil into an exact number");
rb_raise(rb_eTypeError, "can't convert %"PRIsVALUE" into an exact number",
rb_obj_class(v));
}