From: Nobuyoshi Nakada Date: 2009-09-29T12:50:26+09:00 Subject: [ruby-dev:39397] redifition warning for module_function なかだです。 jsonで警告が出ます。 $ ruby -w -rjson -ep /usr/local/lib/ruby/1.9.1/json/common.rb:273: warning: method redefined; discarding old recurse_proc 最小化すると $ ruby -w -e 'module M; module_function; def foo;end; module_function :foo; end' -e:1: warning: method redefined; discarding old foo module_functionによって定義された特異メソッドをもう一度 module_functionで再定義ということのようです。実際には同じaliasの ようなものを作り直すだけなので、この警告は不要ではないかと思います。 Index: method.h =================================================================== --- method.h (revision 25143) +++ method.h (working copy) @@ -75,4 +75,5 @@ typedef struct rb_method_entry_struct { #define UNDEFINED_METHOD_ENTRY_P(me) (!(me) || !(me)->def || (me)->def->type == VM_METHOD_TYPE_UNDEF) +#define CFUNC_EQUAL(cf1, cf2) ((cf1).func == (cf2).func && (cf1).argc == (cf2).argc) void rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_flag_t noex); Index: vm_method.c =================================================================== --- vm_method.c (revision 25143) +++ vm_method.c (working copy) @@ -142,4 +142,34 @@ rb_free_method_entry(rb_method_entry_t * } +static inline int +method_definition_equal(const rb_method_definition_t *def1, const rb_method_definition_t *def2) +{ + if (def1 == def2) return TRUE; + if (!def1 || !def2) return FALSE; + if (def1->type != def2->type) return FALSE; + if (def1->original_id != def2->original_id) return FALSE; + switch (def1->type) { + case VM_METHOD_TYPE_CFUNC: + if (!CFUNC_EQUAL(def1->body.cfunc, def2->body.cfunc)) return FALSE; + break; + case VM_METHOD_TYPE_IVAR: + case VM_METHOD_TYPE_ATTRSET: + if (def1->body.attr_id != def2->body.attr_id) return FALSE; + break; + case VM_METHOD_TYPE_BMETHOD: + if (def1->body.proc != def2->body.proc) return FALSE; + break; + case VM_METHOD_TYPE_ISEQ: + if (def1->body.iseq != def2->body.iseq) return FALSE; + break; + case VM_METHOD_TYPE_OPTIMIZED: + if (def1->body.optimize_type != def2->body.optimize_type) return FALSE; + break; + default: + return FALSE; + } + return TRUE; +} + static rb_method_entry_t * rb_add_method_def(VALUE klass, ID mid, rb_method_type_t type, rb_method_definition_t *def, rb_method_flag_t noex) @@ -180,5 +210,5 @@ rb_add_method_def(VALUE klass, ID mid, r rb_method_definition_t *old_def = old_me->def; - if (old_def == def) return old_me; + if (method_definition_equal(old_def, def)) return old_me; rb_vm_check_redefinition_opt_method(old_me); Index: test/ruby/test_class.rb =================================================================== --- test/ruby/test_class.rb (revision 25143) +++ test/ruby/test_class.rb (working copy) @@ -99,4 +99,15 @@ class TestClass < Test::Unit::TestCase end + def verbose_warning + class << (stderr = "") + alias write << + end + stderr, $stderr, verbose, $VERBOSE = $stderr, stderr, $VERBOSE, true + yield + ensure + stderr, $stderr, $VERBOSE = $stderr, stderr, verbose + return stderr + end + def test_module_function c = Class.new @@ -104,4 +115,27 @@ class TestClass < Test::Unit::TestCase Module.instance_method(:module_function).bind(c).call(:foo) end + stderr = verbose_warning do + Module.new do + def foo; end + def foo; end + end + end + assert_match(/method redefined; discarding old foo/, stderr) + stderr = verbose_warning do + Module.new do + def foo; end + alias bar foo + alias bar foo + end + end + assert_equal("", stderr) + stderr = verbose_warning do + Module.new do + module_function + def foo; end + module_function :foo + end + end + assert_equal("", stderr) end -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦