なかだです。

初期化済み定数の警告で、定義された場所を表示するのはどうでしょうか。

$ ./ruby -e X=1 -e X=2
-e:2: warning: already initialized constant X at -e:1


Index: class.c =================================================================== --- class.c (revision 23168) +++ class.c (working copy) @@ -26,4 +26,5 @@ class_alloc(VALUE flags, VALUE klass) RCLASS_IV_TBL(obj) = 0; RCLASS_M_TBL(obj) = 0; + RCLASS_LOC_TBL(obj) = 0; RCLASS_SUPER(obj) = 0; RCLASS_IV_INDEX_TBL(obj) = 0; Index: gc.c =================================================================== --- gc.c (revision 23168) +++ gc.c (working copy) @@ -1552,4 +1552,5 @@ gc_mark_children(rb_objspace_t *objspace mark_tbl(objspace, RCLASS_M_TBL(obj), lev); mark_tbl(objspace, RCLASS_IV_TBL(obj), lev); + mark_tbl(objspace, RCLASS_LOC_TBL(obj), lev); ptr = RCLASS_SUPER(obj); goto again; Index: variable.c =================================================================== --- variable.c (revision 23168) +++ variable.c (working copy) @@ -1512,4 +1512,12 @@ { return rb_const_get_0(klass, id, Qtrue, Qfalse); +} + +static void +remove_loc(VALUE mod, ID id) +{ + if (RCLASS_LOC_TBL(mod)) { + st_delete(RCLASS_LOC_TBL(mod), &id, 0); + } } @@ -1545,4 +1553,5 @@ rb_mod_remove_const(VALUE mod, VALUE nam val = Qnil; } + remove_loc(mod, id); return val; } @@ -1712,11 +1721,28 @@ mod_av_set(VALUE klass, ID id, VALUE val } else if (isconst) { - VALUE value = Qfalse; + st_data_t value = Qfalse; if (st_lookup(RCLASS_IV_TBL(klass), id, &value)) { - if (value == Qundef) - autoload_delete(klass, id); - else - rb_warn("already initialized %s %s", dest, rb_id2name(id)); + if ((VALUE)value == Qundef) + autoload_delete(klass, id); + else { + VALUE file = Qnil; + long line = 0; + if (st_lookup(RCLASS_LOC_TBL(klass), id, &value)) { + file = RNODE(value)->nd_lit; + line = RNODE(value)->nd_cnt; + } + if (!RTEST(file)) { + rb_warn("already initialized %s %s", dest, rb_id2name(id)); + } + else if (!line) { + rb_warn("already initialized %s %s in %s", dest, rb_id2name(id), + RSTRING_PTR(file)); + } + else { + rb_warn("already initialized %s %s at %s:%ld", dest, rb_id2name(id), + RSTRING_PTR(file), line); + } + } } } @@ -1726,4 +1752,12 @@ mod_av_set(VALUE klass, ID id, VALUE val } st_insert(RCLASS_IV_TBL(klass), id, val); + if (!NIL_P(ruby_verbose)) { + NODE *loc = NEW_LIT(rb_sourcefile_str()); + loc->nd_cnt = rb_sourceline(); + if (!RCLASS_LOC_TBL(klass)) { + RCLASS_LOC_TBL(klass) = st_init_numtable(); + } + st_insert(RCLASS_LOC_TBL(klass), id, (st_data_t)loc); + } } @@ -1958,4 +1992,5 @@ rb_mod_remove_cvar(VALUE mod, VALUE name if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), &n, &val)) { + remove_loc(mod, id); return (VALUE)val; } Index: vm.c =================================================================== --- vm.c (revision 23168) +++ vm.c (working copy) @@ -749,9 +749,17 @@ const char * rb_sourcefile(void) { + VALUE file = rb_sourcefile_str(); + if (file) return RSTRING_PTR(file); + return 0; +} + +VALUE +rb_sourcefile_str(void) +{ rb_thread_t *th = GET_THREAD(); rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); if (cfp) { - return RSTRING_PTR(cfp->iseq->filename); + return cfp->iseq->filename; } else { Index: include/ruby/intern.h =================================================================== --- include/ruby/intern.h (revision 23168) +++ include/ruby/intern.h (working copy) @@ -200,4 +200,5 @@ void rb_check_frozen(VALUE); int rb_sourceline(void); const char *rb_sourcefile(void); +VALUE rb_sourcefile_str(void); #if defined(NFDBITS) && defined(HAVE_RB_FD_INIT) Index: include/ruby/ruby.h =================================================================== --- include/ruby/ruby.h (revision 23168) +++ include/ruby/ruby.h (working copy) @@ -581,4 +581,5 @@ typedef struct { VALUE super; struct st_table *iv_tbl; + struct st_table *loc_tbl; } rb_classext_t; @@ -591,4 +592,5 @@ struct RClass { #define RCLASS_IV_TBL(c) (RCLASS(c)->ptr->iv_tbl) #define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl) +#define RCLASS_LOC_TBL(c) (RCLASS(c)->ptr->loc_tbl) #define RCLASS_SUPER(c) (RCLASS(c)->ptr->super) #define RCLASS_IV_INDEX_TBL(c) (RCLASS(c)->iv_index_tbl)
-- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦