From 581be44edea511652692f2a609264f55b27b7c9a Mon Sep 17 00:00:00 2001 From: nobu Date: Fri, 15 Sep 2017 02:01:59 +0000 Subject: [PATCH] object.c: fix conversion failure message * object.c (convert_type_with_id): fix failure message for explicit conversion. rb_convert_type_with_id and rb_check_convert_type_with_id are not only for implicit conversions. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59919 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- object.c | 44 ++++++++++++++++++++++++---------------- test/ruby/test_object.rb | 1 + 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/object.c b/object.c index 0f91a1b43e..7f5e89f6bc 100644 --- a/object.c +++ b/object.c @@ -2885,13 +2885,33 @@ static const struct conv_method_tbl { }; #define IMPLICIT_CONVERSIONS 7 +static int +conv_method_index(const char *method) +{ + static const char prefix[] = "to_"; + + if (strncmp(prefix, method, sizeof(prefix)-1) == 0) { + const char *const meth = &method[sizeof(prefix)-1]; + int i; + for (i=0; i < numberof(conv_method_names); i++) { + if (conv_method_names[i].method[0] == meth[0] && + strcmp(conv_method_names[i].method, meth) == 0) { + return i; + } + } + } + return numberof(conv_method_names); +} + static VALUE convert_type_with_id(VALUE val, const char *tname, ID method, int raise, int index) { VALUE r = rb_check_funcall(val, method, 0, 0); if (r == Qundef) { if (raise) { - const char *msg = index < IMPLICIT_CONVERSIONS ? + const char *msg = + ((index < 0 ? conv_method_index(rb_id2name(method)) : index) + < IMPLICIT_CONVERSIONS) ? "no implicit conversion of" : "can't convert"; const char *cname = NIL_P(val) ? "nil" : val == Qtrue ? "true" : @@ -2911,21 +2931,9 @@ convert_type_with_id(VALUE val, const char *tname, ID method, int raise, int ind static VALUE convert_type(VALUE val, const char *tname, const char *method, int raise) { - ID m = 0; - int i = numberof(conv_method_names); - static const char prefix[] = "to_"; - - if (strncmp(prefix, method, sizeof(prefix)-1) == 0) { - const char *const meth = &method[sizeof(prefix)-1]; - for (i=0; i < numberof(conv_method_names); i++) { - if (conv_method_names[i].method[0] == meth[0] && - strcmp(conv_method_names[i].method, meth) == 0) { - m = conv_method_names[i].id; - break; - } - } - } - if (!m) m = rb_intern(method); + int i = conv_method_index(method); + ID m = i < numberof(conv_method_names) ? + conv_method_names[i].id : rb_intern(method); return convert_type_with_id(val, tname, m, raise, i); } @@ -2973,7 +2981,7 @@ rb_convert_type_with_id(VALUE val, int type, const char *tname, ID method) VALUE v; if (TYPE(val) == type) return val; - v = convert_type_with_id(val, tname, method, TRUE, 0); + v = convert_type_with_id(val, tname, method, TRUE, -1); if (TYPE(v) != type) { conversion_mismatch(val, tname, RSTRING_PTR(rb_id2str(method)), v); } @@ -3017,7 +3025,7 @@ rb_check_convert_type_with_id(VALUE val, int type, const char *tname, ID method) /* always convert T_DATA */ if (TYPE(val) == type && type != T_DATA) return val; - v = convert_type_with_id(val, tname, method, FALSE, 0); + v = convert_type_with_id(val, tname, method, FALSE, -1); if (NIL_P(v)) return Qnil; if (TYPE(v) != type) { conversion_mismatch(val, tname, RSTRING_PTR(rb_id2str(method)), v); diff --git a/test/ruby/test_object.rb b/test/ruby/test_object.rb index e7d623283f..e55a09dc23 100644 --- a/test/ruby/test_object.rb +++ b/test/ruby/test_object.rb @@ -923,6 +923,7 @@ class TestObject < Test::Unit::TestCase _issue = "Bug #7539" assert_raise_with_message(TypeError, "can't convert Array into Integer") {Integer([42])} assert_raise_with_message(TypeError, 'no implicit conversion of Array into Integer') {[].first([42])} + assert_raise_with_message(TypeError, "can't convert Array into Rational") {Rational([42])} end def test_copied_ivar_memory_leak