ruby-changes:39881
From: nobu <ko1@a...>
Date: Mon, 28 Sep 2015 11:41:12 +0900 (JST)
Subject: [ruby-changes:39881] nobu:r51962 (trunk): preserve encodings in error messages
nobu 2015-09-28 11:40:46 +0900 (Mon, 28 Sep 2015) New Revision: 51962 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=51962 Log: preserve encodings in error messages Modified files: trunk/array.c trunk/bignum.c trunk/complex.c trunk/enum.c trunk/enumerator.c trunk/error.c trunk/numeric.c trunk/sprintf.c trunk/test/-ext-/typeddata/test_typeddata.rb trunk/test/ruby/test_array.rb trunk/test/ruby/test_bignum.rb trunk/test/ruby/test_complex.rb trunk/test/ruby/test_enum.rb trunk/test/ruby/test_enumerator.rb trunk/test/ruby/test_exception.rb trunk/test/ruby/test_time.rb trunk/time.c Index: complex.c =================================================================== --- complex.c (revision 51961) +++ complex.c (revision 51962) @@ -1020,8 +1020,8 @@ nucomp_coerce(VALUE self, VALUE other) https://github.com/ruby/ruby/blob/trunk/complex.c#L1020 if (RB_TYPE_P(other, T_COMPLEX)) return rb_assoc_new(other, self); - rb_raise(rb_eTypeError, "%s can't be coerced into %s", - rb_obj_classname(other), rb_obj_classname(self)); + rb_raise(rb_eTypeError, "%"PRIsVALUE" can't be coerced into %"PRIsVALUE, + rb_obj_class(other), rb_obj_class(self)); return Qnil; } Index: array.c =================================================================== --- array.c (revision 51961) +++ array.c (revision 51962) @@ -2170,10 +2170,11 @@ rb_ary_to_h(VALUE ary) https://github.com/ruby/ruby/blob/trunk/array.c#L2170 long i; VALUE hash = rb_hash_new(); for (i=0; i<RARRAY_LEN(ary); i++) { - VALUE key_value_pair = rb_check_array_type(rb_ary_elt(ary, i)); + const VALUE elt = rb_ary_elt(ary, i); + const VALUE key_value_pair = rb_check_array_type(elt); if (NIL_P(key_value_pair)) { - rb_raise(rb_eTypeError, "wrong element type %s at %ld (expected array)", - rb_builtin_class_name(rb_ary_elt(ary, i)), i); + rb_raise(rb_eTypeError, "wrong element type %"PRIsVALUE" at %ld (expected array)", + rb_obj_class(elt), i); } if (RARRAY_LEN(key_value_pair) != 2) { rb_raise(rb_eArgError, "wrong array length at %ld (expected 2, was %ld)", Index: time.c =================================================================== --- time.c (revision 51961) +++ time.c (revision 51962) @@ -202,8 +202,8 @@ divmodv(VALUE n, VALUE d, VALUE *q, VALU https://github.com/ruby/ruby/blob/trunk/time.c#L202 tmp = rb_funcall(n, id_divmod, 1, d); ary = rb_check_array_type(tmp); if (NIL_P(ary)) { - rb_raise(rb_eTypeError, "unexpected divmod result: into %s", - rb_obj_classname(tmp)); + rb_raise(rb_eTypeError, "unexpected divmod result: into %"PRIsVALUE, + rb_obj_class(tmp)); } *q = rb_ary_entry(ary, 0); *r = rb_ary_entry(ary, 1); @@ -560,8 +560,8 @@ wdivmod(wideval_t wn, wideval_t wd, wide https://github.com/ruby/ruby/blob/trunk/time.c#L560 tmp = rb_funcall(w2v(wn), id_divmod, 1, w2v(wd)); ary = rb_check_array_type(tmp); if (NIL_P(ary)) { - rb_raise(rb_eTypeError, "unexpected divmod result: into %s", - rb_obj_classname(tmp)); + rb_raise(rb_eTypeError, "unexpected divmod result: into %"PRIsVALUE, + rb_obj_class(tmp)); } *wq = v2w(rb_ary_entry(ary, 0)); *wr = v2w(rb_ary_entry(ary, 1)); @@ -641,8 +641,10 @@ num_exact(VALUE v) https://github.com/ruby/ruby/blob/trunk/time.c#L641 default: typeerror: - rb_raise(rb_eTypeError, "can't convert %s into an exact number", - NIL_P(v) ? "nil" : rb_obj_classname(v)); + 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)); } return v; } @@ -2322,7 +2324,7 @@ static struct timespec https://github.com/ruby/ruby/blob/trunk/time.c#L2324 time_timespec(VALUE num, int interval) { struct timespec t; - const char *tstr = interval ? "time interval" : "time"; + const char *const tstr = interval ? "time interval" : "time"; VALUE i, f, ary; #ifndef NEGATIVE_TIME_T @@ -2382,8 +2384,8 @@ time_timespec(VALUE num, int interval) https://github.com/ruby/ruby/blob/trunk/time.c#L2384 t.tv_nsec = NUM2LONG(f); } else { - rb_raise(rb_eTypeError, "can't convert %s into %s", - rb_obj_classname(num), tstr); + rb_raise(rb_eTypeError, "can't convert %"PRIsVALUE" into %s", + rb_obj_class(num), tstr); } break; } Index: enumerator.c =================================================================== --- enumerator.c (revision 51961) +++ enumerator.c (revision 51962) @@ -1245,8 +1245,8 @@ generator_initialize(int argc, VALUE *ar https://github.com/ruby/ruby/blob/trunk/enumerator.c#L1245 if (!rb_obj_is_proc(proc)) rb_raise(rb_eTypeError, - "wrong argument type %s (expected Proc)", - rb_obj_classname(proc)); + "wrong argument type %"PRIsVALUE" (expected Proc)", + rb_obj_class(proc)); if (rb_block_given_p()) { rb_warn("given block not used"); @@ -1771,8 +1771,8 @@ lazy_zip(int argc, VALUE *argv, VALUE ob https://github.com/ruby/ruby/blob/trunk/enumerator.c#L1771 if (NIL_P(v)) { for (; i < argc; i++) { if (!rb_respond_to(argv[i], id_each)) { - rb_raise(rb_eTypeError, "wrong argument type %s (must respond to :each)", - rb_obj_classname(argv[i])); + rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)", + rb_obj_class(argv[i])); } } ary = rb_ary_new4(argc, argv); Index: enum.c =================================================================== --- enum.c (revision 51961) +++ enum.c (revision 51962) @@ -2483,8 +2483,8 @@ enum_zip(int argc, VALUE *argv, VALUE ob https://github.com/ruby/ruby/blob/trunk/enum.c#L2483 CONST_ID(conv, "to_enum"); for (i=0; i<argc; i++) { if (!rb_respond_to(argv[i], id_each)) { - rb_raise(rb_eTypeError, "wrong argument type %s (must respond to :each)", - rb_obj_classname(argv[i])); + rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)", + rb_obj_class(argv[i])); } argv[i] = rb_funcall(argv[i], conv, 1, ID2SYM(id_each)); } Index: sprintf.c =================================================================== --- sprintf.c (revision 51961) +++ sprintf.c (revision 51962) @@ -1338,6 +1338,26 @@ ruby__sfvextra(rb_printf_buffer *fp, siz https://github.com/ruby/ruby/blob/trunk/sprintf.c#L1338 rb_raise(rb_eRuntimeError, "rb_vsprintf reentered"); } if (sign == '+') { + if (RB_TYPE_P(value, T_CLASS)) { +# define LITERAL(str) (*sz = rb_strlen_lit(str), str) + + if (value == rb_cNilClass) { + return LITERAL("nil"); + } + else if (value == rb_cFixnum) { + return LITERAL("Fixnum"); + } + else if (value == rb_cSymbol) { + return LITERAL("Symbol"); + } + else if (value == rb_cTrueClass) { + return LITERAL("true"); + } + else if (value == rb_cFalseClass) { + return LITERAL("false"); + } +# undef LITERAL + } value = rb_inspect(value); } else { Index: error.c =================================================================== --- error.c (revision 51961) +++ error.c (revision 51962) @@ -520,9 +520,8 @@ rb_builtin_type_name(int t) https://github.com/ruby/ruby/blob/trunk/error.c#L520 return 0; } -#define builtin_class_name rb_builtin_class_name -const char * -rb_builtin_class_name(VALUE x) +static const char * +builtin_class_name(VALUE x) { const char *etype; @@ -542,6 +541,17 @@ rb_builtin_class_name(VALUE x) https://github.com/ruby/ruby/blob/trunk/error.c#L541 etype = "false"; } else { + etype = NULL; + } + return etype; +} + +const char * +rb_builtin_class_name(VALUE x) +{ + const char *etype = builtin_class_name(x); + + if (!etype) { etype = rb_obj_classname(x); } return etype; @@ -560,8 +570,13 @@ rb_check_type(VALUE x, int t) https://github.com/ruby/ruby/blob/trunk/error.c#L570 if (xt != t || (xt == T_DATA && RTYPEDDATA_P(x))) { const char *tname = rb_builtin_type_name(t); if (tname) { - rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)", - builtin_class_name(x), tname); + const char *cname = builtin_class_name(x); + if (cname) + rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)", + cname, tname); + else + rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected %s)", + rb_obj_class(x), tname); } if (xt > T_MASK && xt <= 0x3f) { rb_fatal("unknown type 0x%x (0x%x given, probably comes from extension library for ruby 1.8)", t, xt); @@ -594,19 +609,23 @@ void * https://github.com/ruby/ruby/blob/trunk/error.c#L609 rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type) { const char *etype; - static const char mesg[] = "wrong argument type %s (expected %s)"; if (!RB_TYPE_P(obj, T_DATA)) { + wrong_type: etype = builtin_class_name(obj); - rb_raise(rb_eTypeError, mesg, etype, data_type->wrap_struct_name); + if (!etype) + rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected %s)", + rb_obj_class(obj), data_type->wrap_struct_name); + wrong_datatype: + rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)", + etype, data_type->wrap_struct_name); } if (!RTYPEDDATA_P(obj)) { - etype = rb_obj_classname(obj); - rb_raise(rb_eTypeError, mesg, etype, data_type->wrap_struct_name); + goto wrong_type; } else if (!rb_typeddata_inherited_p(RTYPEDDATA_TYPE(obj), data_type)) { etype = RTYPEDDATA_TYPE(obj)->wrap_struct_name; - rb_raise(rb_eTypeError, mesg, etype, data_type->wrap_struct_name); + goto wrong_datatype; } return DATA_PTR(obj); } Index: numeric.c =================================================================== --- numeric.c (revision 51961) +++ numeric.c (revision 51962) @@ -295,7 +295,8 @@ do_coerce(VALUE *x, VALUE *y, int err) https://github.com/ruby/ruby/blob/trunk/numeric.c#L295 if (!RB_TYPE_P(ary, T_ARRAY) || RARRAY_LEN(ary) != 2) { if (err) { rb_raise(rb_eTypeError, "coerce must return [x, y]"); - } else if (!NIL_P(ary)) { + } + else if (!NIL_P(ary)) { rb_warn("Bad return value for #coerce, called by numerical comparison operators."); rb_warn("#coerce must return [x, y]. The next release will raise an error for this."); } Index: bignum.c =================================================================== --- bignum.c (revision 51961) +++ bignum.c (revision 51962) @@ -6834,8 +6834,8 @@ rb_big_coerce(VALUE x, VALUE y) https://github.com/ruby/ruby/blob/trunk/bignum.c#L6834 y = rb_int2big(FIX2LONG(y)); } else if (!RB_BIGNUM_TYPE_P(y)) { - rb_raise(rb_eTypeError, "can't coerce %s to Bignum", - rb_obj_classname(y)); + rb_raise(rb_eTypeError, "can't coerce %"PRIsVALUE" to Bignum", + rb_obj_class(y)); } return rb_assoc_new(y, x); } Index: test/ruby/test_enumerator.rb =================================================================== --- test/ruby/test_enumerator.rb (revision 51961) +++ test/ruby/test_enumerator.rb (revision 51962) @@ -433,6 +433,18 @@ class TestEnumerator < Test::Unit::TestC https://github.com/ruby/ruby/blob/trunk/test/ruby/test_enumerator.rb#L433 assert_raise(RuntimeError) { g.__send__ :initialize, proc { |y| y << 4 << 5 } } + + g = Enumerator::Generator.new(proc {|y| y << 4 << 5; :foo }) + a = [] + assert_equal(:foo, g.each {|x| a << x }) + assert_equal([4, 5], a) + + assert_raise(LocalJumpError) {Enumerator::Generator.new} + assert_raise(TypeError) {Enumerator::Generator.new(1)} + obj = eval("class C\u{1f5ff}; self; end").new + assert_raise_with_message(TypeError, /C\u{1f5ff}/) { + Enumerator::Generator.new(obj) + } end def test_generator_args Index: test/ruby/test_array.rb =================================================================== --- test/ruby/test_array.rb (revision 51961) +++ test/ruby/test_array.rb (revision 51962) @@ -1543,6 +1543,8 @@ class TestArray < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_array.rb#L1543 [[:first_one, :ok], :not_ok].to_h } assert_equal "wrong element type Symbol at 1 (expected array)", e.message + array = [eval("class C\u{1f5ff}; self; end").new] + assert_raise_with_message(TypeError, /C\u{1f5ff}/) {array.to_h} e = assert_raise(ArgumentError) { [[:first_one, :ok], [1, 2], [:not_ok]].to_h } Index: test/ruby/test_bignum.rb =================================================================== --- test/ruby/test_bignum.rb (revision 51961) +++ test/ruby/test_bignum.rb (revision 51962) @@ -568,6 +568,8 @@ class TestBignum < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_bignum.rb#L568 def test_coerce assert_equal([T64P, T31P], T31P.coerce(T64P)) assert_raise(TypeError) { T31P.coerce(nil) } + obj = eval("class C\u{1f5ff}; self; end").new + assert_raise_with_message(TypeError, /C\u{1f5ff}/) { T31P.coerce(obj) } end def test_abs Index: test/ruby/test_enum.rb =================================================================== --- test/ruby/test_enum.rb (revision 51961) +++ test/ruby/test_enum.rb (revision 51962) @@ -457,6 +457,8 @@ class TestEnumerable < Test::Unit::TestC https://github.com/ruby/ruby/blob/trunk/test/ruby/test_enum.rb#L457 assert_equal([[1, 3], [2, 4], [3, nil], [1, nil], [2, nil]], @obj.zip(ary)) def ary.to_ary; [5, 6]; end assert_equal([[1, 5], [2, 6], [3, nil], [1, nil], [2, nil]], @obj.zip(ary)) + obj = eval("class C\u{1f5ff}; self; end").new + assert_raise_with_message(TypeError, /C\u{1f5ff}/) {(1..1).zip(obj)} end def test_take Index: test/ruby/test_time.rb =================================================================== --- test/ruby/test_time.rb (revision 51961) +++ test/ruby/test_time.rb (revision 51962) @@ -417,6 +417,11 @@ class TestTime < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_time.rb#L417 } } assert_raise(ArgumentError) { m.sleep(-1) } + assert_raise(TypeError) { m.sleep("") } + assert_raise(TypeError) { sleep("") } + obj = eval("class C\u{1f5ff}; self; end").new + assert_raise_with_message(TypeError, /C\u{1f5ff}/) {m.sleep(obj)} + assert_raise_with_message(TypeError, /C\u{1f5ff}/) {sleep(obj)} end def test_to_f Index: test/ruby/test_exception.rb =================================================================== --- test/ruby/test_exception.rb (revision 51961) +++ test/ruby/test_exception.rb (revision 51962) @@ -302,6 +302,10 @@ class TestException < Test::Unit::TestCa https://github.com/ruby/ruby/blob/trunk/test/ruby/test_exception.rb#L302 assert_raise_with_message(TypeError, /C\u{4032}/) do [*o] end + obj = eval("class C\u{1f5ff}; self; end").new + assert_raise_with_message(TypeError, /C\u{1f5ff}/) do + Class.new {include obj} + end end def test_errat Index: test/ruby/test_complex.rb =================================================================== --- test/ruby/test_complex.rb (revision 51961) +++ test/ruby/test_complex.rb (revision 51962) @@ -427,6 +427,9 @@ class Complex_Test < Test::Unit::TestCas https://github.com/ruby/ruby/blob/trunk/test/ruby/test_complex.rb#L427 assert_equal([Complex(Rational(2)),Complex(1)], Complex(1).coerce(Rational(2))) assert_equal([Complex(2),Complex(1)], Complex(1).coerce(Complex(2))) + + obj = eval("class C\u{1f5ff}; self; end").new + assert_raise_with_message(TypeError, /C\u{1f5ff}/) { Complex(1).coerce(obj) } end class ObjectX Index: test/-ext-/typeddata/test_typeddata.rb =================================================================== --- test/-ext-/typeddata/test_typeddata.rb (revision 51961) +++ test/-ext-/typeddata/test_typeddata.rb (revision 51962) @@ -12,5 +12,8 @@ class Test_TypedData < Test::Unit::TestC https://github.com/ruby/ruby/blob/trunk/test/-ext-/typeddata/test_typeddata.rb#L12 assert_raise_with_message(TypeError, "wrong argument type Fixnum (expected typed_data)") {Bug::TypedData.check(0)} assert_raise_with_message(TypeError, "wrong argument type String (expected typed_data)") {Bug::TypedData.check("a")} + + obj = eval("class C\u{1f5ff}; self; end").new + assert_raise_with_message(TypeError, /C\u{1f5ff}/) {Bug::TypedData.check(obj)} end end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/