Skip to content

Commit bc752a4

Browse files
byrooteregon
authored andcommitted
Refactor type error to be more consistent
[Bug #21864] Co-Authored-By: Benoit Daloze <eregontp@gmail.com>
1 parent 1afadda commit bc752a4

36 files changed

Lines changed: 158 additions & 112 deletions

complex.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "internal/array.h"
2121
#include "internal/class.h"
2222
#include "internal/complex.h"
23+
#include "internal/error.h"
2324
#include "internal/math.h"
2425
#include "internal/numeric.h"
2526
#include "internal/object.h"
@@ -2411,7 +2412,7 @@ nucomp_convert(VALUE klass, VALUE a1, VALUE a2, int raise)
24112412
{
24122413
if (NIL_P(a1) || NIL_P(a2)) {
24132414
if (!raise) return Qnil;
2414-
rb_raise(rb_eTypeError, "can't convert nil into Complex");
2415+
rb_cant_convert(Qnil, "Complex");
24152416
}
24162417

24172418
if (RB_TYPE_P(a1, T_STRING)) {

depend

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1892,6 +1892,7 @@ complex.$(OBJEXT): $(top_srcdir)/internal/box.h
18921892
complex.$(OBJEXT): $(top_srcdir)/internal/class.h
18931893
complex.$(OBJEXT): $(top_srcdir)/internal/compilers.h
18941894
complex.$(OBJEXT): $(top_srcdir)/internal/complex.h
1895+
complex.$(OBJEXT): $(top_srcdir)/internal/error.h
18951896
complex.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
18961897
complex.$(OBJEXT): $(top_srcdir)/internal/gc.h
18971898
complex.$(OBJEXT): $(top_srcdir)/internal/imemo.h
@@ -9963,6 +9964,7 @@ numeric.$(OBJEXT): $(top_srcdir)/internal/class.h
99639964
numeric.$(OBJEXT): $(top_srcdir)/internal/compilers.h
99649965
numeric.$(OBJEXT): $(top_srcdir)/internal/complex.h
99659966
numeric.$(OBJEXT): $(top_srcdir)/internal/enumerator.h
9967+
numeric.$(OBJEXT): $(top_srcdir)/internal/error.h
99669968
numeric.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
99679969
numeric.$(OBJEXT): $(top_srcdir)/internal/gc.h
99689970
numeric.$(OBJEXT): $(top_srcdir)/internal/hash.h
@@ -13221,6 +13223,7 @@ rational.$(OBJEXT): $(top_srcdir)/internal/box.h
1322113223
rational.$(OBJEXT): $(top_srcdir)/internal/class.h
1322213224
rational.$(OBJEXT): $(top_srcdir)/internal/compilers.h
1322313225
rational.$(OBJEXT): $(top_srcdir)/internal/complex.h
13226+
rational.$(OBJEXT): $(top_srcdir)/internal/error.h
1322413227
rational.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
1322513228
rational.$(OBJEXT): $(top_srcdir)/internal/gc.h
1322613229
rational.$(OBJEXT): $(top_srcdir)/internal/imemo.h
@@ -13231,6 +13234,7 @@ rational.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
1323113234
rational.$(OBJEXT): $(top_srcdir)/internal/serial.h
1323213235
rational.$(OBJEXT): $(top_srcdir)/internal/set_table.h
1323313236
rational.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
13237+
rational.$(OBJEXT): $(top_srcdir)/internal/string.h
1323413238
rational.$(OBJEXT): $(top_srcdir)/internal/variable.h
1323513239
rational.$(OBJEXT): $(top_srcdir)/internal/vm.h
1323613240
rational.$(OBJEXT): $(top_srcdir)/internal/warnings.h
@@ -13248,6 +13252,7 @@ rational.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
1324813252
rational.$(OBJEXT): {$(VPATH)}config.h
1324913253
rational.$(OBJEXT): {$(VPATH)}constant.h
1325013254
rational.$(OBJEXT): {$(VPATH)}defines.h
13255+
rational.$(OBJEXT): {$(VPATH)}encindex.h
1325113256
rational.$(OBJEXT): {$(VPATH)}encoding.h
1325213257
rational.$(OBJEXT): {$(VPATH)}id.h
1325313258
rational.$(OBJEXT): {$(VPATH)}id_table.h
@@ -17669,6 +17674,7 @@ time.$(OBJEXT): $(top_srcdir)/internal/bits.h
1766917674
time.$(OBJEXT): $(top_srcdir)/internal/box.h
1767017675
time.$(OBJEXT): $(top_srcdir)/internal/compar.h
1767117676
time.$(OBJEXT): $(top_srcdir)/internal/compilers.h
17677+
time.$(OBJEXT): $(top_srcdir)/internal/error.h
1767217678
time.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
1767317679
time.$(OBJEXT): $(top_srcdir)/internal/gc.h
1767417680
time.$(OBJEXT): $(top_srcdir)/internal/hash.h

error.c

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2758,6 +2758,68 @@ nometh_err_private_call_p(VALUE self)
27582758
return rb_attr_get(self, id_private_call_p);
27592759
}
27602760

2761+
static const char *
2762+
type_err_cname(VALUE val)
2763+
{
2764+
if (NIL_P(val)) {
2765+
return "nil";
2766+
}
2767+
else if (val == Qtrue) {
2768+
return "true";
2769+
}
2770+
else if (val == Qfalse) {
2771+
return "false";
2772+
}
2773+
return NULL;
2774+
}
2775+
2776+
NORETURN(static void type_err_raise(VALUE val, const char *tname, const char *msg));
2777+
static void
2778+
type_err_raise(VALUE val, const char *tname, const char *msg)
2779+
{
2780+
const char *cname = type_err_cname(val);
2781+
rb_encoding *enc = rb_utf8_encoding();
2782+
if (cname) {
2783+
rb_enc_raise(enc, rb_eTypeError, "%s %s into %s", msg, cname, tname);
2784+
}
2785+
rb_enc_raise(enc, rb_eTypeError, "%s %"PRIsVALUE" into %s", msg, rb_obj_class(val), tname);
2786+
}
2787+
2788+
NORETURN(void rb_no_implicit_conversion(VALUE val, const char *tname));
2789+
void
2790+
rb_no_implicit_conversion(VALUE val, const char *tname)
2791+
{
2792+
type_err_raise(val, tname, "no implicit conversion of");
2793+
}
2794+
2795+
NORETURN(void rb_cant_convert(VALUE val, const char *tname));
2796+
void
2797+
rb_cant_convert(VALUE val, const char *tname)
2798+
{
2799+
type_err_raise(val, tname, "can't convert");
2800+
}
2801+
2802+
NORETURN(void rb_cant_convert_invalid_return(VALUE val, const char *tname, const char *method_name, VALUE ret));
2803+
void
2804+
rb_cant_convert_invalid_return(VALUE val, const char *tname, const char *method_name, VALUE ret)
2805+
{
2806+
const char *cname = type_err_cname(val);
2807+
rb_encoding *enc = rb_utf8_encoding();
2808+
if (cname) {
2809+
rb_enc_raise(
2810+
enc, rb_eTypeError, "can't convert %s into %s (%s#%s gives %s)",
2811+
cname, tname, cname, method_name, type_err_cname(ret));
2812+
}
2813+
VALUE klass = rb_obj_class(val);
2814+
const char *retname = type_err_cname(ret);
2815+
if (!retname) {
2816+
retname = rb_obj_classname(ret);
2817+
}
2818+
rb_enc_raise(
2819+
enc, rb_eTypeError, "can't convert %"PRIsVALUE" into %s (%"PRIsVALUE"#%s gives %s)",
2820+
klass, tname, klass, method_name, retname);
2821+
}
2822+
27612823
void
27622824
rb_invalid_str(const char *str, const char *type)
27632825
{

internal/error.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,9 @@ static inline void Check_Type(VALUE v, enum ruby_value_type t);
186186
static inline bool rb_typeddata_is_instance_of_inline(VALUE obj, const rb_data_type_t *data_type);
187187
#define rb_typeddata_is_instance_of rb_typeddata_is_instance_of_inline
188188
void rb_bug_without_die(const char *fmt, ...);
189+
NORETURN(void rb_no_implicit_conversion(VALUE val, const char *tname));
190+
NORETURN(void rb_cant_convert(VALUE val, const char *tname));
191+
NORETURN(void rb_cant_convert_invalid_return(VALUE val, const char *tname, const char *method_name, VALUE ret));
189192

190193
RUBY_SYMBOL_EXPORT_BEGIN
191194
/* error.c (export) */

numeric.c

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "internal/compilers.h"
3131
#include "internal/complex.h"
3232
#include "internal/enumerator.h"
33+
#include "internal/error.h"
3334
#include "internal/gc.h"
3435
#include "internal/hash.h"
3536
#include "internal/numeric.h"
@@ -3102,7 +3103,7 @@ rb_num2long(VALUE val)
31023103
{
31033104
again:
31043105
if (NIL_P(val)) {
3105-
rb_raise(rb_eTypeError, "no implicit conversion from nil to integer");
3106+
rb_no_implicit_conversion(val, "Integer");
31063107
}
31073108

31083109
if (FIXNUM_P(val)) return FIX2LONG(val);
@@ -3130,7 +3131,7 @@ rb_num2ulong_internal(VALUE val, int *wrap_p)
31303131
{
31313132
again:
31323133
if (NIL_P(val)) {
3133-
rb_raise(rb_eTypeError, "no implicit conversion of nil into Integer");
3134+
rb_no_implicit_conversion(val, "Integer");
31343135
}
31353136

31363137
if (FIXNUM_P(val)) {
@@ -3373,7 +3374,7 @@ LONG_LONG
33733374
rb_num2ll(VALUE val)
33743375
{
33753376
if (NIL_P(val)) {
3376-
rb_raise(rb_eTypeError, "no implicit conversion from nil");
3377+
rb_no_implicit_conversion(val, "Integer");
33773378
}
33783379

33793380
if (FIXNUM_P(val)) return (LONG_LONG)FIX2LONG(val);
@@ -3390,11 +3391,8 @@ rb_num2ll(VALUE val)
33903391
else if (RB_BIGNUM_TYPE_P(val)) {
33913392
return rb_big2ll(val);
33923393
}
3393-
else if (RB_TYPE_P(val, T_STRING)) {
3394-
rb_raise(rb_eTypeError, "no implicit conversion from string");
3395-
}
3396-
else if (RB_TYPE_P(val, T_TRUE) || RB_TYPE_P(val, T_FALSE)) {
3397-
rb_raise(rb_eTypeError, "no implicit conversion from boolean");
3394+
else if (val == Qfalse || val == Qtrue || RB_TYPE_P(val, T_STRING)) {
3395+
rb_no_implicit_conversion(val, "Integer");
33983396
}
33993397

34003398
val = rb_to_int(val);
@@ -3405,7 +3403,7 @@ unsigned LONG_LONG
34053403
rb_num2ull(VALUE val)
34063404
{
34073405
if (NIL_P(val)) {
3408-
rb_raise(rb_eTypeError, "no implicit conversion of nil into Integer");
3406+
rb_no_implicit_conversion(val, "Integer");
34093407
}
34103408
else if (FIXNUM_P(val)) {
34113409
return (LONG_LONG)FIX2LONG(val); /* this is FIX2LONG, intended */

object.c

Lines changed: 18 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -3332,19 +3332,12 @@ convert_type_with_id(VALUE val, const char *tname, ID method, int raise, int ind
33323332
VALUE r = rb_check_funcall(val, method, 0, 0);
33333333
if (UNDEF_P(r)) {
33343334
if (raise) {
3335-
const char *msg =
3336-
((index < 0 ? conv_method_index(rb_id2name(method)) : index)
3337-
< IMPLICIT_CONVERSIONS) ?
3338-
"no implicit conversion of" : "can't convert";
3339-
const char *cname = NIL_P(val) ? "nil" :
3340-
val == Qtrue ? "true" :
3341-
val == Qfalse ? "false" :
3342-
NULL;
3343-
if (cname)
3344-
rb_raise(rb_eTypeError, "%s %s into %s", msg, cname, tname);
3345-
rb_raise(rb_eTypeError, "%s %"PRIsVALUE" into %s", msg,
3346-
rb_obj_class(val),
3347-
tname);
3335+
if ((index < 0 ? conv_method_index(rb_id2name(method)) : index) < IMPLICIT_CONVERSIONS) {
3336+
rb_no_implicit_conversion(val, tname);
3337+
}
3338+
else {
3339+
rb_cant_convert(val, tname);
3340+
}
33483341
}
33493342
return Qnil;
33503343
}
@@ -3360,17 +3353,6 @@ convert_type(VALUE val, const char *tname, const char *method, int raise)
33603353
return convert_type_with_id(val, tname, m, raise, i);
33613354
}
33623355

3363-
/*! \private */
3364-
NORETURN(static void conversion_mismatch(VALUE, const char *, const char *, VALUE));
3365-
static void
3366-
conversion_mismatch(VALUE val, const char *tname, const char *method, VALUE result)
3367-
{
3368-
VALUE cname = rb_obj_class(val);
3369-
rb_raise(rb_eTypeError,
3370-
"can't convert %"PRIsVALUE" to %s (%"PRIsVALUE"#%s gives %"PRIsVALUE")",
3371-
cname, tname, cname, method, rb_obj_class(result));
3372-
}
3373-
33743356
VALUE
33753357
rb_convert_type(VALUE val, int type, const char *tname, const char *method)
33763358
{
@@ -3379,7 +3361,7 @@ rb_convert_type(VALUE val, int type, const char *tname, const char *method)
33793361
if (TYPE(val) == type) return val;
33803362
v = convert_type(val, tname, method, TRUE);
33813363
if (TYPE(v) != type) {
3382-
conversion_mismatch(val, tname, method, v);
3364+
rb_cant_convert_invalid_return(val, tname, method, v);
33833365
}
33843366
return v;
33853367
}
@@ -3393,7 +3375,7 @@ rb_convert_type_with_id(VALUE val, int type, const char *tname, ID method)
33933375
if (TYPE(val) == type) return val;
33943376
v = convert_type_with_id(val, tname, method, TRUE, -1);
33953377
if (TYPE(v) != type) {
3396-
conversion_mismatch(val, tname, RSTRING_PTR(rb_id2str(method)), v);
3378+
rb_cant_convert_invalid_return(val, tname, rb_id2name(method), v);
33973379
}
33983380
return v;
33993381
}
@@ -3408,7 +3390,7 @@ rb_check_convert_type(VALUE val, int type, const char *tname, const char *method
34083390
v = convert_type(val, tname, method, FALSE);
34093391
if (NIL_P(v)) return Qnil;
34103392
if (TYPE(v) != type) {
3411-
conversion_mismatch(val, tname, method, v);
3393+
rb_cant_convert_invalid_return(val, tname, method, v);
34123394
}
34133395
return v;
34143396
}
@@ -3424,7 +3406,7 @@ rb_check_convert_type_with_id(VALUE val, int type, const char *tname, ID method)
34243406
v = convert_type_with_id(val, tname, method, FALSE, -1);
34253407
if (NIL_P(v)) return Qnil;
34263408
if (TYPE(v) != type) {
3427-
conversion_mismatch(val, tname, RSTRING_PTR(rb_id2str(method)), v);
3409+
rb_cant_convert_invalid_return(val, tname, rb_id2name(method), v);
34283410
}
34293411
return v;
34303412
}
@@ -3450,7 +3432,7 @@ rb_to_integer_with_id_exception(VALUE val, const char *method, ID mid, int raise
34503432
return Qnil;
34513433
}
34523434
if (!RB_INTEGER_TYPE_P(v)) {
3453-
conversion_mismatch(val, "Integer", method, v);
3435+
rb_cant_convert_invalid_return(val, "Integer", method, v);
34543436
}
34553437
GET_EC()->cfp = current_cfp;
34563438
return v;
@@ -3527,7 +3509,7 @@ rb_convert_to_integer(VALUE val, int base, int raise_exception)
35273509
}
35283510
else if (NIL_P(val)) {
35293511
if (!raise_exception) return Qnil;
3530-
rb_raise(rb_eTypeError, "can't convert nil into Integer");
3512+
rb_cant_convert(val, "Integer");
35313513
}
35323514

35333515
tmp = rb_protect(rb_check_to_int, val, NULL);
@@ -3821,18 +3803,6 @@ rat2dbl_without_to_f(VALUE x)
38213803
}
38223804
/*! \endcond */
38233805

3824-
static inline void
3825-
conversion_to_float(VALUE val)
3826-
{
3827-
special_const_to_float(val, "can't convert ", " into Float");
3828-
}
3829-
3830-
static inline void
3831-
implicit_conversion_to_float(VALUE val)
3832-
{
3833-
special_const_to_float(val, "no implicit conversion to float from ", "");
3834-
}
3835-
38363806
static int
38373807
to_float(VALUE *valp, int raise_exception)
38383808
{
@@ -3846,7 +3816,7 @@ to_float(VALUE *valp, int raise_exception)
38463816
return T_FLOAT;
38473817
}
38483818
else if (raise_exception) {
3849-
conversion_to_float(val);
3819+
rb_cant_convert(val, "Float");
38503820
}
38513821
}
38523822
else {
@@ -3926,8 +3896,7 @@ static VALUE
39263896
numeric_to_float(VALUE val)
39273897
{
39283898
if (!rb_obj_is_kind_of(val, rb_cNumeric)) {
3929-
rb_raise(rb_eTypeError, "can't convert %"PRIsVALUE" into Float",
3930-
rb_obj_class(val));
3899+
rb_cant_convert(val, "Float");
39313900
}
39323901
return rb_convert_type_with_id(val, T_FLOAT, "Float", id_to_f);
39333902
}
@@ -3971,7 +3940,7 @@ rb_num_to_dbl(VALUE val)
39713940
return rb_float_flonum_value(val);
39723941
}
39733942
else {
3974-
conversion_to_float(val);
3943+
rb_cant_convert(val, "Float");
39753944
}
39763945
}
39773946
else {
@@ -4005,7 +3974,7 @@ rb_num2dbl(VALUE val)
40053974
return rb_float_flonum_value(val);
40063975
}
40073976
else {
4008-
implicit_conversion_to_float(val);
3977+
rb_no_implicit_conversion(val, "Float");
40093978
}
40103979
}
40113980
else {
@@ -4017,7 +3986,7 @@ rb_num2dbl(VALUE val)
40173986
case T_RATIONAL:
40183987
return rat2dbl_without_to_f(val);
40193988
case T_STRING:
4020-
rb_raise(rb_eTypeError, "no implicit conversion to float from string");
3989+
rb_no_implicit_conversion(val, "Float");
40213990
default:
40223991
break;
40233992
}
@@ -4111,7 +4080,7 @@ rb_Hash(VALUE val)
41114080
if (NIL_P(tmp)) {
41124081
if (RB_TYPE_P(val, T_ARRAY) && RARRAY_LEN(val) == 0)
41134082
return rb_hash_new();
4114-
rb_raise(rb_eTypeError, "can't convert %s into Hash", rb_obj_classname(val));
4083+
rb_cant_convert(val, "Hash");
41154084
}
41164085
return tmp;
41174086
}

rational.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "internal.h"
2828
#include "internal/array.h"
2929
#include "internal/complex.h"
30+
#include "internal/error.h"
3031
#include "internal/gc.h"
3132
#include "internal/numeric.h"
3233
#include "internal/object.h"
@@ -2562,7 +2563,7 @@ nurat_convert(VALUE klass, VALUE numv, VALUE denv, int raise)
25622563

25632564
if (NIL_P(a1) || NIL_P(a2)) {
25642565
if (!raise) return Qnil;
2565-
rb_raise(rb_eTypeError, "can't convert nil into Rational");
2566+
rb_cant_convert(Qnil, "Rational");
25662567
}
25672568

25682569
if (RB_TYPE_P(a1, T_COMPLEX)) {

0 commit comments

Comments
 (0)