Location of already initialized constant

Issue #1374 has been updated by Yusuke E…

Assignee changed from Yukihiro M. to Nobuyoshi N.
Priority changed from Low to Normal

遠藤です。

trunk に入れましょう。なかださんお願いします。


Yusuke E. [email protected]

Feature #1374: location of already initialized constant

Author: Nobuyoshi N.
Status: Assigned
Priority: Normal
Assignee: Nobuyoshi N.
Category: core
Target version: 2.0.0

=begin
なかだです。

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

$ ./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はできる。
中田 伸悦
=end