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

ruby-changes:61016

From: Benoit <ko1@a...>
Date: Wed, 6 May 2020 07:22:29 +0900 (JST)
Subject: [ruby-changes:61016] 48d509cefc (master): Document rb_equal() and clarify the relation with Kernel#===

https://git.ruby-lang.org/ruby.git/commit/?id=48d509cefc

From 48d509cefc376df8af0ad0e08a09aecbd78f4f10 Mon Sep 17 00:00:00 2001
From: Benoit Daloze <eregontp@g...>
Date: Wed, 6 May 2020 00:11:42 +0200
Subject: Document rb_equal() and clarify the relation with Kernel#===

* Multiple times people have been confused and believed rb_equal()
  called #=== but it does not, it calls #==.
* This optimization has a subtle side effect for Float::NAN,
  which is now documented.

diff --git a/object.c b/object.c
index fead841..1e314e1 100644
--- a/object.c
+++ b/object.c
@@ -141,7 +141,22 @@ rb_obj_setup(VALUE obj, VALUE klass, VALUE type) https://github.com/ruby/ruby/blob/trunk/object.c#L141
  * Same as \c Object#===, case equality.
  *++
  */
+static VALUE
+case_equal(VALUE obj1, VALUE obj2) {
+    /* The default implementation of #=== is
+     * to call #== with the rb_equal() optimization. */
+    return rb_equal(obj1, obj2);
+}
 
+/*!
+ * This function is an optimized version of calling #==.
+ * It checks equality between two objects by first doing a fast
+ * identity check using using C's == (same as BasicObject#equal?).
+ * If that check fails, it calls #== dynamically.
+ * This optimization actually affects semantics,
+ * as Float::NAN == Float::NAN is false,
+ * but rb_equal(Float::NAN, Float::NAN) is true!
+ */
 VALUE
 rb_equal(VALUE obj1, VALUE obj2)
 {
@@ -4598,7 +4613,7 @@ InitVM_Object(void) https://github.com/ruby/ruby/blob/trunk/object.c#L4613
     rb_define_private_method(rb_cModule, "method_undefined", rb_obj_dummy1, 1);
 
     rb_define_method(rb_mKernel, "nil?", rb_false, 0);
-    rb_define_method(rb_mKernel, "===", rb_equal, 1);
+    rb_define_method(rb_mKernel, "===", case_equal, 1);
     rb_define_method(rb_mKernel, "=~", rb_obj_match, 1);
     rb_define_method(rb_mKernel, "!~", rb_obj_not_match, 1);
     rb_define_method(rb_mKernel, "eql?", rb_obj_equal, 1);
@@ -4665,7 +4680,7 @@ InitVM_Object(void) https://github.com/ruby/ruby/blob/trunk/object.c#L4680
     rb_define_method(rb_cNilClass, "&", false_and, 1);
     rb_define_method(rb_cNilClass, "|", false_or, 1);
     rb_define_method(rb_cNilClass, "^", false_xor, 1);
-    rb_define_method(rb_cNilClass, "===", rb_equal, 1);
+    rb_define_method(rb_cNilClass, "===", case_equal, 1);
 
     rb_define_method(rb_cNilClass, "nil?", rb_true, 0);
     rb_undef_alloc_func(rb_cNilClass);
@@ -4751,7 +4766,7 @@ InitVM_Object(void) https://github.com/ruby/ruby/blob/trunk/object.c#L4766
     rb_define_method(rb_cTrueClass, "&", true_and, 1);
     rb_define_method(rb_cTrueClass, "|", true_or, 1);
     rb_define_method(rb_cTrueClass, "^", true_xor, 1);
-    rb_define_method(rb_cTrueClass, "===", rb_equal, 1);
+    rb_define_method(rb_cTrueClass, "===", case_equal, 1);
     rb_undef_alloc_func(rb_cTrueClass);
     rb_undef_method(CLASS_OF(rb_cTrueClass), "new");
 
@@ -4763,7 +4778,7 @@ InitVM_Object(void) https://github.com/ruby/ruby/blob/trunk/object.c#L4778
     rb_define_method(rb_cFalseClass, "&", false_and, 1);
     rb_define_method(rb_cFalseClass, "|", false_or, 1);
     rb_define_method(rb_cFalseClass, "^", false_xor, 1);
-    rb_define_method(rb_cFalseClass, "===", rb_equal, 1);
+    rb_define_method(rb_cFalseClass, "===", case_equal, 1);
     rb_undef_alloc_func(rb_cFalseClass);
     rb_undef_method(CLASS_OF(rb_cFalseClass), "new");
 }
-- 
cgit v0.10.2


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

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