1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

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
This commit is contained in:
nobu 2017-09-15 02:01:59 +00:00
parent 92e3ffdf78
commit 581be44ede
2 changed files with 27 additions and 18 deletions

View file

@ -2885,13 +2885,33 @@ static const struct conv_method_tbl {
}; };
#define IMPLICIT_CONVERSIONS 7 #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 static VALUE
convert_type_with_id(VALUE val, const char *tname, ID method, int raise, int index) convert_type_with_id(VALUE val, const char *tname, ID method, int raise, int index)
{ {
VALUE r = rb_check_funcall(val, method, 0, 0); VALUE r = rb_check_funcall(val, method, 0, 0);
if (r == Qundef) { if (r == Qundef) {
if (raise) { 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"; "no implicit conversion of" : "can't convert";
const char *cname = NIL_P(val) ? "nil" : const char *cname = NIL_P(val) ? "nil" :
val == Qtrue ? "true" : val == Qtrue ? "true" :
@ -2911,21 +2931,9 @@ convert_type_with_id(VALUE val, const char *tname, ID method, int raise, int ind
static VALUE static VALUE
convert_type(VALUE val, const char *tname, const char *method, int raise) convert_type(VALUE val, const char *tname, const char *method, int raise)
{ {
ID m = 0; int i = conv_method_index(method);
int i = numberof(conv_method_names); ID m = i < numberof(conv_method_names) ?
static const char prefix[] = "to_"; conv_method_names[i].id : rb_intern(method);
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);
return convert_type_with_id(val, tname, m, raise, i); 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; VALUE v;
if (TYPE(val) == type) return val; 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) { if (TYPE(v) != type) {
conversion_mismatch(val, tname, RSTRING_PTR(rb_id2str(method)), v); 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 */ /* always convert T_DATA */
if (TYPE(val) == type && type != T_DATA) return val; 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 (NIL_P(v)) return Qnil;
if (TYPE(v) != type) { if (TYPE(v) != type) {
conversion_mismatch(val, tname, RSTRING_PTR(rb_id2str(method)), v); conversion_mismatch(val, tname, RSTRING_PTR(rb_id2str(method)), v);

View file

@ -923,6 +923,7 @@ class TestObject < Test::Unit::TestCase
_issue = "Bug #7539" _issue = "Bug #7539"
assert_raise_with_message(TypeError, "can't convert Array into Integer") {Integer([42])} 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, 'no implicit conversion of Array into Integer') {[].first([42])}
assert_raise_with_message(TypeError, "can't convert Array into Rational") {Rational([42])}
end end
def test_copied_ivar_memory_leak def test_copied_ivar_memory_leak