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

ruby-changes:52135

From: usa <ko1@a...>
Date: Mon, 13 Aug 2018 22:48:33 +0900 (JST)
Subject: [ruby-changes:52135] usa:r64343 (trunk): Fix problem about notimplemented case

usa	2018-08-13 22:48:27 +0900 (Mon, 13 Aug 2018)

  New Revision: 64343

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

  Log:
    Fix problem about notimplemented case
    
    Re-revert r64340, and take care about notimplemented case.

  Modified files:
    trunk/test/ruby/test_module.rb
    trunk/vm_method.c
Index: vm_method.c
===================================================================
--- vm_method.c	(revision 64342)
+++ vm_method.c	(revision 64343)
@@ -1278,14 +1278,44 @@ rb_mod_undef_method(int argc, VALUE *arg https://github.com/ruby/ruby/blob/trunk/vm_method.c#L1278
     return mod;
 }
 
+static rb_method_visibility_t
+check_definition_visibility(VALUE mod, int argc, VALUE *argv)
+{
+    const rb_method_entry_t *me;
+    VALUE mid, include_super, lookup_mod = mod;
+    int inc_super;
+    ID id;
+
+    rb_scan_args(argc, argv, "11", &mid, &include_super);
+    id = rb_check_id(&mid);
+    if (!id) return METHOD_VISI_UNDEF;
+
+    if (argc == 1) {
+	inc_super = 1;
+    } else {
+	inc_super = RTEST(include_super);
+	if (!inc_super) {
+	    lookup_mod = RCLASS_ORIGIN(mod);
+	}
+    }
+
+    me = rb_method_entry_without_refinements(lookup_mod, id, NULL);
+    if (me) {
+	if (me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) return METHOD_VISI_UNDEF;
+	if (!inc_super && me->owner != mod) return METHOD_VISI_UNDEF;
+	return METHOD_ENTRY_VISI(me);
+    }
+    return METHOD_VISI_UNDEF;
+}
+
 /*
  *  call-seq:
- *     mod.method_defined?(symbol)    -> true or false
- *     mod.method_defined?(string)    -> true or false
+ *     mod.method_defined?(symbol, inherit=true)    -> true or false
+ *     mod.method_defined?(string, inherit=true)    -> true or false
  *
  *  Returns +true+ if the named method is defined by
- *  _mod_ (or its included modules and, if _mod_ is a class,
- *  its ancestors). Public and protected methods are matched.
+ *  _mod_.  If _inherit_ is set, the lookup will also search _mod_'s
+ *  ancestors. Public and protected methods are matched.
  *  String arguments are converted to symbols.
  *
  *     module A
@@ -1306,6 +1336,8 @@ rb_mod_undef_method(int argc, VALUE *arg https://github.com/ruby/ruby/blob/trunk/vm_method.c#L1336
  *     A.method_defined? :method1              #=> true
  *     C.method_defined? "method1"             #=> true
  *     C.method_defined? "method2"             #=> true
+ *     C.method_defined? "method2", true       #=> true
+ *     C.method_defined? "method2", false      #=> false
  *     C.method_defined? "method3"             #=> true
  *     C.method_defined? "protected_method1"   #=> true
  *     C.method_defined? "method4"             #=> false
@@ -1313,37 +1345,26 @@ rb_mod_undef_method(int argc, VALUE *arg https://github.com/ruby/ruby/blob/trunk/vm_method.c#L1345
  */
 
 static VALUE
-rb_mod_method_defined(VALUE mod, VALUE mid)
+rb_mod_method_defined(int argc, VALUE *argv, VALUE mod)
 {
-    ID id = rb_check_id(&mid);
-    if (!id || !rb_method_boundp(mod, id, 1)) {
-	return Qfalse;
-    }
-    return Qtrue;
-
+    rb_method_visibility_t visi = check_definition_visibility(mod, argc, argv);
+    return (visi == METHOD_VISI_PUBLIC || visi == METHOD_VISI_PROTECTED) ? Qtrue : Qfalse;
 }
 
 static VALUE
-check_definition(VALUE mod, VALUE mid, rb_method_visibility_t visi)
+check_definition(VALUE mod, int argc, VALUE *argv, rb_method_visibility_t visi)
 {
-    const rb_method_entry_t *me;
-    ID id = rb_check_id(&mid);
-    if (!id) return Qfalse;
-    me = rb_method_entry_without_refinements(mod, id, NULL);
-    if (me) {
-	if (METHOD_ENTRY_VISI(me) == visi) return Qtrue;
-    }
-    return Qfalse;
+    return (check_definition_visibility(mod, argc, argv) == visi) ? Qtrue : Qfalse;
 }
 
 /*
  *  call-seq:
- *     mod.public_method_defined?(symbol)   -> true or false
- *     mod.public_method_defined?(string)   -> true or false
+ *     mod.public_method_defined?(symbol, inherit=true)   -> true or false
+ *     mod.public_method_defined?(string, inherit=true)   -> true or false
  *
  *  Returns +true+ if the named public method is defined by
- *  _mod_ (or its included modules and, if _mod_ is a class,
- *  its ancestors).
+ *  _mod_.  If _inherit_ is set, the lookup will also search _mod_'s
+ *  ancestors.
  *  String arguments are converted to symbols.
  *
  *     module A
@@ -1358,26 +1379,28 @@ check_definition(VALUE mod, VALUE mid, r https://github.com/ruby/ruby/blob/trunk/vm_method.c#L1379
  *       def method3()  end
  *     end
  *
- *     A.method_defined? :method1           #=> true
- *     C.public_method_defined? "method1"   #=> true
- *     C.public_method_defined? "method2"   #=> false
- *     C.method_defined? "method2"          #=> true
+ *     A.method_defined? :method1                 #=> true
+ *     C.public_method_defined? "method1"         #=> true
+ *     C.public_method_defined? "method1", true   #=> true
+ *     C.public_method_defined? "method1", false  #=> true
+ *     C.public_method_defined? "method2"         #=> false
+ *     C.method_defined? "method2"                #=> true
  */
 
 static VALUE
-rb_mod_public_method_defined(VALUE mod, VALUE mid)
+rb_mod_public_method_defined(int argc, VALUE *argv, VALUE mod)
 {
-    return check_definition(mod, mid, METHOD_VISI_PUBLIC);
+    return check_definition(mod, argc, argv, METHOD_VISI_PUBLIC);
 }
 
 /*
  *  call-seq:
- *     mod.private_method_defined?(symbol)    -> true or false
- *     mod.private_method_defined?(string)    -> true or false
+ *     mod.private_method_defined?(symbol, inherit=true)    -> true or false
+ *     mod.private_method_defined?(string, inherit=true)    -> true or false
  *
  *  Returns +true+ if the named private method is defined by
- *  _ mod_ (or its included modules and, if _mod_ is a class,
- *  its ancestors).
+ *  _mod_.  If _inherit_ is set, the lookup will also search _mod_'s
+ *  ancestors.
  *  String arguments are converted to symbols.
  *
  *     module A
@@ -1392,26 +1415,28 @@ rb_mod_public_method_defined(VALUE mod, https://github.com/ruby/ruby/blob/trunk/vm_method.c#L1415
  *       def method3()  end
  *     end
  *
- *     A.method_defined? :method1            #=> true
- *     C.private_method_defined? "method1"   #=> false
- *     C.private_method_defined? "method2"   #=> true
- *     C.method_defined? "method2"           #=> false
+ *     A.method_defined? :method1                   #=> true
+ *     C.private_method_defined? "method1"          #=> false
+ *     C.private_method_defined? "method2"          #=> true
+ *     C.private_method_defined? "method2", true    #=> true
+ *     C.private_method_defined? "method2", false   #=> false
+ *     C.method_defined? "method2"                  #=> false
  */
 
 static VALUE
-rb_mod_private_method_defined(VALUE mod, VALUE mid)
+rb_mod_private_method_defined(int argc, VALUE *argv, VALUE mod)
 {
-    return check_definition(mod, mid, METHOD_VISI_PRIVATE);
+    return check_definition(mod, argc, argv, METHOD_VISI_PRIVATE);
 }
 
 /*
  *  call-seq:
- *     mod.protected_method_defined?(symbol)   -> true or false
- *     mod.protected_method_defined?(string)   -> true or false
+ *     mod.protected_method_defined?(symbol, inherit=true)   -> true or false
+ *     mod.protected_method_defined?(string, inherit=true)   -> true or false
  *
  *  Returns +true+ if the named protected method is defined
- *  by _mod_ (or its included modules and, if _mod_ is a
- *  class, its ancestors).
+ *  _mod_.  If _inherit_ is set, the lookup will also search _mod_'s
+ *  ancestors.
  *  String arguments are converted to symbols.
  *
  *     module A
@@ -1426,16 +1451,18 @@ rb_mod_private_method_defined(VALUE mod, https://github.com/ruby/ruby/blob/trunk/vm_method.c#L1451
  *       def method3()  end
  *     end
  *
- *     A.method_defined? :method1              #=> true
- *     C.protected_method_defined? "method1"   #=> false
- *     C.protected_method_defined? "method2"   #=> true
- *     C.method_defined? "method2"             #=> true
+ *     A.method_defined? :method1                    #=> true
+ *     C.protected_method_defined? "method1"         #=> false
+ *     C.protected_method_defined? "method2"         #=> true
+ *     C.protected_method_defined? "method2", true   #=> true
+ *     C.protected_method_defined? "method2", false  #=> false
+ *     C.method_defined? "method2"                   #=> true
  */
 
 static VALUE
-rb_mod_protected_method_defined(VALUE mod, VALUE mid)
+rb_mod_protected_method_defined(int argc, VALUE *argv, VALUE mod)
 {
-    return check_definition(mod, mid, METHOD_VISI_PROTECTED);
+    return check_definition(mod, argc, argv, METHOD_VISI_PROTECTED);
 }
 
 int
@@ -2121,10 +2148,10 @@ Init_eval_method(void) https://github.com/ruby/ruby/blob/trunk/vm_method.c#L2148
     rb_define_private_method(rb_cModule, "private", rb_mod_private, -1);
     rb_define_private_method(rb_cModule, "module_function", rb_mod_modfunc, -1);
 
-    rb_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, 1);
-    rb_define_method(rb_cModule, "public_method_defined?", rb_mod_public_method_defined, 1);
-    rb_define_method(rb_cModule, "private_method_defined?", rb_mod_private_method_defined, 1);
-    rb_define_method(rb_cModule, "protected_method_defined?", rb_mod_protected_method_defined, 1);
+    rb_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, -1);
+    rb_define_method(rb_cModule, "public_method_defined?", rb_mod_public_method_defined, -1);
+    rb_define_method(rb_cModule, "private_method_defined?", rb_mod_private_method_defined, -1);
+    rb_define_method(rb_cModule, "protected_method_defined?", rb_mod_protected_method_defined, -1);
     rb_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1);
     rb_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1);
 
Index: test/ruby/test_module.rb
===================================================================
--- test/ruby/test_module.rb	(revision 64342)
+++ test/ruby/test_module.rb	(revision 64343)
@@ -468,17 +468,42 @@ class TestModule < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_module.rb#L468
   end
 
   def test_method_defined?
-    assert !User.method_defined?(:wombat)
-    assert User.method_defined?(:mixin)
-    assert User.method_defined?(:user)
-    assert User.method_defined?(:user2)
-    assert !User.method_defined?(:user3)
-
-    assert !User.method_defined?("wombat")
-    assert User.method_defined?("mixin")
-    assert User.method_defined?("user")
-    assert User.method_defined?("user2")
-    assert !User.method_defined?("user3")
+    [User, Class.new{include User}, Class.new{prepend User}].each do |klass|
+      [[], [true]].each do |args|
+        assert !klass.method_defined?(:wombat, *args)
+        assert klass.method_defined?(:mixin, *args)
+        assert klass.method_defined?(:user, *args)
+        assert klass.method_defined?(:user2, *args)
+        assert !klass.method_defined?(:user3, *args)
+
+        assert !klass.method_defined?("wombat", *args)
+        assert klass.method_defined?("mixin", *args)
+        assert klass.method_defined?("user", *args)
+        assert klass.method_defined?("user2", *args)
+        assert !klass.method_defined?("user3", *args)
+      end
+    end
+  end
+
+  def test_method_defined_without_include_super
+    assert User.method_defined?(:user, false)
+    assert !User.method_defined?(:mixin, false)
+    assert Mixin.method_defined?(:mixin, false)
+
+    User.const_set(:FOO, c = Class.new)
+
+    c.prepend(User)
+    assert !c.method_defined?(:user, false)
+    c.define_method(:user){}
+    assert c.method_defined?(:user, false)
+
+    assert !c.method_defined?(:mixin, false)
+    c.define_method(:mixin){}
+    assert c.method_defined?(:mixin, false)
+
+    assert !c.method_defined?(:userx, false)
+    c.define_method(:userx){}
+    assert c.method_defined?(:userx, false)
   end
 
   def module_exec_aux
@@ -974,8 +999,8 @@ class TestModule < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_module.rb#L999
   end
 
   def test_method_defined
-    c = Class.new
-    c.class_eval do
+    cl = Class.new
+    def_methods = proc do
       def foo; end
       def bar; end
       def baz; end
@@ -983,33 +1008,47 @@ class TestModule < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_module.rb#L1008
       protected :bar
       private :baz
     end
-
-    assert_equal(true, c.public_method_defined?(:foo))
-    assert_equal(false, c.public_method_defined?(:bar))
-    assert_equal(false, c.public_method_defined?(:baz))
-
-    # Test if string arguments are converted to symbols
-    assert_equal(true, c.public_method_defined?("foo"))
-    assert_equal(false, c.public_method_defined?("bar"))
-    assert_equal(false, c.public_method_defined?("baz"))
-
-    assert_equal(false, c.protected_method_defined?(:foo))
-    assert_equal(true, c.protected_method_defined?(:bar))
-    assert_equal(false, c.protected_method_defined?(:baz))
-
-    # Test if string arguments are converted to symbols
-    assert_equal(false, c.protected_method_defined?("foo"))
-    assert_equal(true, c.protected_method_defined?("bar"))
-    assert_equal(false, c.protected_method_defined?("baz"))
-
-    assert_equal(false, c.private_method_defined?(:foo))
-    assert_equal(false, c.private_method_defined?(:bar))
-    assert_equal(true, c.private_method_defined?(:baz))
-
-    # Test if string arguments are converted to symbols
-    assert_equal(false, c.private_method_defined?("foo"))
-    assert_equal(false, c.private_method_defined?("bar"))
-    assert_equal(true, c.private_method_defined?("baz"))
+    cl.class_eval(&def_methods)
+    sc = Class.new(cl)
+    mod = Module.new(&def_methods)
+    only_prepend = Class.new{prepend(mod)}
+    empty_prepend = cl.clone
+    empty_prepend.prepend(Module.new)
+    overlap_prepend = cl.clone
+    overlap_prepend.prepend(mod)
+
+    [[], [true], [false]].each do |args|
+      [cl, sc, only_prepend, empty_prepend, overlap_prepend].each do |c|
+        always_false = [sc, only_prepend].include?(c) && args == [false]
+
+        assert_equal(always_false ? false : true, c.public_method_defined?(:foo, *args))
+        assert_equal(always_false ? false : false, c.public_method_defined?(:bar, *args))
+        assert_equal(always_false ? false : false, c.public_method_defined?(:baz, *args))
+
+        # Test if string arguments are converted to symbols
+        assert_equal(always_false ? false : true, c.public_method_defined?("foo", *args))
+        assert_equal(always_false ? false : false, c.public_method_defined?("bar", *args))
+        assert_equal(always_false ? false : false, c.public_method_defined?("baz", *args))
+
+        assert_equal(always_false ? false : false, c.protected_method_defined?(:foo, *args))
+        assert_equal(always_false ? false : true, c.protected_method_defined?(:bar, *args))
+        assert_equal(always_false ? false : false, c.protected_method_defined?(:baz, *args))
+
+        # Test if string arguments are converted to symbols
+        assert_equal(always_false ? false : false, c.protected_method_defined?("foo", *args))
+        assert_equal(always_false ? false : true, c.protected_method_defined?("bar", *args))
+        assert_equal(always_false ? false : false, c.protected_method_defined?("baz", *args))
+
+        assert_equal(always_false ? false : false, c.private_method_defined?(:foo, *args))
+        assert_equal(always_false ? false : false, c.private_method_defined?(:bar, *args))
+        assert_equal(always_false ? false : true, c.private_method_defined?(:baz, *args))
+
+        # Test if string arguments are converted to symbols
+        assert_equal(always_false ? false : false, c.private_method_defined?("foo", *args))
+        assert_equal(always_false ? false : false, c.private_method_defined?("bar", *args))
+        assert_equal(always_false ? false : true, c.private_method_defined?("baz", *args))
+      end
+    end
   end
 
   def test_top_public_private

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

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