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

ruby-changes:34294

From: eregon <ko1@a...>
Date: Sat, 7 Jun 2014 22:16:16 +0900 (JST)
Subject: [ruby-changes:34294] eregon:r46375 (trunk): * numeric.c (do_coerce): Add a warning when an exception is raised

eregon	2014-06-07 22:16:01 +0900 (Sat, 07 Jun 2014)

  New Revision: 46375

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=46375

  Log:
    * numeric.c (do_coerce): Add a warning when an exception is raised
      or an invalid value is returned in #coerce called by
      numeric comparison operators and the exception
      thrown by the caller has no information on the failure.
      In the next release such exception should not be rescued or
      should be the cause of the caller exception. nil is accepted
      as the "no possible coercion" return value. See #7688.
    * test/ruby/test_numeric.rb: Add corresponding test.

  Modified files:
    trunk/ChangeLog
    trunk/numeric.c
    trunk/test/ruby/test_numeric.rb
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 46374)
+++ ChangeLog	(revision 46375)
@@ -1,3 +1,15 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Sat Jun  7 22:13:42 2014  Benoit Daloze  <eregontp@g...>
+
+	* numeric.c (do_coerce): Add a warning when an exception is raised
+	  or an invalid value is returned in #coerce called by
+	  numeric comparison operators and the exception
+	  thrown by the caller has no information on the failure.
+	  In the next release such exception should not be rescued or
+	  should be the cause of the caller exception. nil is accepted
+	  as the "no possible coercion" return value. See #7688.
+
+	* test/ruby/test_numeric.rb: Add corresponding test.
+
 Sat Jun  7 18:15:33 2014  Benoit Daloze  <eregontp@g...>
 
 	* numeric.c (bit_coerce): remove constant parameter `err'
Index: numeric.c
===================================================================
--- numeric.c	(revision 46374)
+++ numeric.c	(revision 46375)
@@ -251,6 +251,12 @@ coerce_rescue(VALUE *x) https://github.com/ruby/ruby/blob/trunk/numeric.c#L251
     return Qnil;		/* dummy */
 }
 
+static VALUE
+coerce_rescue_quiet(VALUE *x)
+{
+    return Qundef;
+}
+
 static int
 do_coerce(VALUE *x, VALUE *y, int err)
 {
@@ -266,10 +272,18 @@ do_coerce(VALUE *x, VALUE *y, int err) https://github.com/ruby/ruby/blob/trunk/numeric.c#L272
 	return FALSE;
     }
 
-    ary = rb_rescue(coerce_body, (VALUE)a, err ? coerce_rescue : 0, (VALUE)a);
+    ary = rb_rescue(coerce_body, (VALUE)a, err ? coerce_rescue : coerce_rescue_quiet, (VALUE)a);
+    if (ary == Qundef) {
+	rb_warn("Numerical comparison operators will no more rescue exceptions of #coerce");
+	rb_warn("in the next release. Return nil in #coerce if the coercion is impossible.");
+	return FALSE;
+    }
     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)) {
+	    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.");
 	}
 	return FALSE;
     }
Index: test/ruby/test_numeric.rb
===================================================================
--- test/ruby/test_numeric.rb	(revision 46374)
+++ test/ruby/test_numeric.rb	(revision 46375)
@@ -59,6 +59,23 @@ class TestNumeric < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_numeric.rb#L59
     end
     assert_equal(-1, -a)
 
+    bug7688 = '[ruby-core:51389] [Bug #7688]'
+    DummyNumeric.class_eval do
+      remove_method :coerce
+      def coerce(x); raise StandardError; end
+    end
+    assert_raise_with_message(TypeError, /can't be coerced into /) { 1 + a }
+    warn = /will no more rescue exceptions of #coerce.+ in the next release/m
+    assert_warn(warn, bug7688) { assert_raise(ArgumentError) { 1 < a } }
+
+    DummyNumeric.class_eval do
+      remove_method :coerce
+      def coerce(x); :bad_return_value; end
+    end
+    assert_raise_with_message(TypeError, "coerce must return [x, y]") { 1 + a }
+    warn = /Bad return value for #coerce.+next release will raise an error/m
+    assert_warn(warn, bug7688) { assert_raise(ArgumentError) { 1 < a } }
+
   ensure
     DummyNumeric.class_eval do
       remove_method :coerce

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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