[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]