[Feature:1.9] location of already initialized constant

e$B$J$+$@$G$9!#e(B

e$B=i4|2=:Q$_Dj?t$N7Y9p$G!"Dj5A$5$l$?>l=j$rI=<($9$k$N$O$I$&$G$7$g$&$+!#e(B

$ ./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© (RCLASS©->ptr->iv_tbl)
#define RCLASS_M_TBL© (RCLASS©->m_tbl)
+#define RCLASS_LOC_TBL© (RCLASS©->ptr->loc_tbl)
#define RCLASS_SUPER© (RCLASS©->ptr->super)
#define RCLASS_IV_INDEX_TBL© (RCLASS©->iv_index_tbl)

e$B%A%1%C%He(B #1374 e$B$,99?7$5$l$^$7$?!#e(B (by Yusuke E.)

Target version 1.9.xe$B$K%;%C%He(B

e$B1sF#$G$9!#e(B

e$B$3$N%Q%C%A$Oe(B rb_classext_t e$B$r$$$8$k$N$G!"e(Bprivate constant
e$B$H$H$b$Ke(B
1.9.3 e$B$rL;X$7$^$7$g$&!#e(B

e$B$H$$$&$3$H$Ge(B target e$B$re(B 1.9.x e$B$K$7$^$9!#e(B


Yusuke E. [email protected]

http://redmine.ruby-lang.org/issues/show/1374