Feature #2366: private constant
http://redmine.ruby-lang.org/issues/show/2366
e$B5/I<<Te(B: Yusuke E.
e$B%9%F!<%?%9e(B: Open, e$BM%@hEYe(B: Normal
e$BC4Ev<Te(B: Yukihiro M., e$B%+%F%4%je(B: core, Target version:
1.9.x
e$B1sF#$G$9!#e(B
e$B:#$Ne(B Ruby e$B$K$O!"%/%i%9$,8x3+e(B API
e$B$+$I$&$+$rEA$($k<jCJ$,%I%-%e%a%s%He(B
e$B$7$+$"$j$^$;$s!#$=$N$?$a!“e(BERB::Compiler
e$B$J$I!”%i%$%V%i%j$NCf$N8x3+e(B
e$B$G$J$$e(B (e$B$H;W$o$l$ke(B) inner class
e$B$r30$+$i<+M3$K;2>H$G$-$F$7$^$$$^$9!#e(B
e$B$3$l$rKI$0$?$a$K$O!"F?L>%/%i%9$rMQ$$$FDj5A$9$l$PBgJ,1#JC$G$-$^$9$,!“e(B
e$B5-=R$,AjEvHQ;($K$J$C$F$7$^$$$^$9!#$^$?!”$=$N$h$&$K$7$F$7$^$&$H!"e(B
e$B!VHs8x3+$H$$$&$N$O>5CN$N>e$G4:$($F;H$$$?$$!W$H$$$&MW5a$KEz$($K$/$/e(B
e$B$J$j$^$9!#e(B
e$B$=$3$G!"Dj?t$Ke(B public/private
[email protected]$r;XDj$G$-$k$h$&$K$9$k$N$O$I$&e(B
e$B$G$7$g$&$+!#e(B
module SomeMod
class PublicInnerCls
end
class PrivateInnerCls
end
# PrivateInnerCls e$B$re(B private e$B$K$9$ke(B
private_constant :PrivateInnerCls
end
public e$B$JDj?t$O=>Mh$I$*$j;2>H$G$-$ke(B
p SomeMod::PublicInnerCls #=> SomeMod::PublicInnerCls
private e$B$JDj?t$r30$+$i;2>H$7$h$&$H$9$k$HNc30e(B
p SomeMod::PrivateInnerCls #=> private constant (RuntimeError)
e$BF1$8%9%3!<%W$+$i$O;2>H$G$-$ke(B (e$BK>$`$J$i<+J,$NB-$r7b$F$ke(B)
p SomeMod.module_eval { PrivateInnerCls } #=>
SomeMod::PrivateInnerCls
p(module SomeMod; PrivateInnerCls; end) #=>
SomeMod::PrivateInnerCls
e$BMW$9$k$K!"%a%=%C%I$Ne(B public/private e$B$HF1$846$8$G$9!#e(B
e$B:Y$+$$;EMM$O5M$a$F$$$^$;$s$,!“e(Bproof of concept
e$B$N%Q%C%A$rIU$1$^$9!#e(B
1 e$BDj?t$4$H$Ke(B 2
e$BMWAG$NG[Ns$r:n$C$F$7$^$&$N$G!”$A$c$s$H$7$?<BAu$OI,MWe(B
[email protected]$H;W$$$^$9!#e(B
e$B$I$s$J$b$N$G$7$g$&$+!#e(B
e$B$A$J$_$K$3$NDs0F$N$-$C$+$1$Oe(B [ruby-dev:39677] e$B$G$9!#e(B
diff --git a/variable.c b/variable.c
index 779a8e8…db3a81c 100644
— a/variable.c
+++ b/variable.c
@@ -1525,6 +1525,33 @@ rb_autoload_p(VALUE mod, ID id)
return load && (file = load->nd_lit) ? file : Qnil;
}
+void
+rb_change_const_visibility(VALUE klass, ID id, VALUE ex)
+{
- VALUE value, tmp;
- int mod_retry = 0;
- tmp = klass;
- while (RTEST(tmp)) {
- VALUE am = 0;
- while (RCLASS_IV_TBL(tmp) && st_lookup(RCLASS_IV_TBL(tmp),
(st_data_t)id, &value)) { -
if (value == Qundef) {
- if (am == tmp) break;
- am = tmp;
- rb_autoload_load(tmp, id);
- continue;
-
}
-
if (tmp == rb_cObject && klass != rb_cObject) {
- rb_warn(“toplevel constant %s referenced by %s::%s”,
-
rb_id2name(id), rb_class2name(klass), rb_id2name(id));
-
}
-
RARRAY_PTR(value)[1] = ex;
-
return;
- }
- tmp = RCLASS_SUPER(tmp);
- }
+}
static VALUE
rb_const_get_0(VALUE klass, ID id, int exclude, int recurse)
{
@@ -1546,7 +1573,10 @@ rb_const_get_0(VALUE klass, ID id, int exclude,
int recurse)
rb_warn(“toplevel constant %s referenced by %s::%s”,
rb_id2name(id), rb_class2name(klass), rb_id2name(id));
}
-
return value;
-
if (!RARRAY_PTR(value)[1]) {
- rb_raise(rb_eRuntimeError, “private constant”);
-
}
-
}return RARRAY_PTR(value)[0];
if (!recurse && klass != rb_cObject) break;
tmp = RCLASS_SUPER(tmp);
@@ -1798,11 +1828,13 @@ mod_av_set(VALUE klass, ID id, VALUE val, int
isconst)
void
rb_const_set(VALUE klass, ID id, VALUE val)
{ - VALUE ary;
if (NIL_P(klass)) {
rb_raise(rb_eTypeError, “no class/module to define constant %s”,
rb_id2name(id));
}
- mod_av_set(klass, id, val, TRUE);
- ary = rb_ary_new3(2, val, Qtrue);
- mod_av_set(klass, id, ary, TRUE);
}
void
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 0660c7d…e3e789e 100644
— a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1141,7 +1141,7 @@ vm_get_ev_const(rb_thread_t *th, const rb_iseq_t
*iseq,
return 1;
}
else {
-
return val;
-
}return RARRAY_PTR(val)[0]; } }
diff --git a/vm_method.c b/vm_method.c
index 557583f…40b125a 100644
— a/vm_method.c
+++ b/vm_method.c
@@ -1038,6 +1038,30 @@ rb_mod_private_method(int argc, VALUE *argv,
VALUE obj)
return obj;
}
+static void
+set_const_visibility(VALUE self, int argc, VALUE *argv, VALUE ex)
+{
- int i;
- extern void rb_change_const_visibility(VALUE klass, ID id, VALUE
ex); - secure_visibility(self);
- for (i = 0; i < argc; i++) {
- rb_change_const_visibility(self, rb_to_id(argv[i]), ex);
- }
- rb_clear_cache_by_class(self);
+}
+static VALUE
+rb_mod_public_constant(int argc, VALUE *argv, VALUE obj)
+{
- set_const_visibility(obj, argc, argv, Qtrue);
+}
+static VALUE
+rb_mod_private_constant(int argc, VALUE *argv, VALUE obj)
+{
- set_const_visibility(obj, argc, argv, Qfalse);
+}
/*
- call-seq:
-
public
@@ -1250,6 +1274,8 @@ Init_eval_method(void)
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);
-
rb_define_method(rb_cModule, “public_constant”,
rb_mod_public_constant, -1); -
rb_define_method(rb_cModule, “private_constant”,
rb_mod_private_constant, -1);rb_define_singleton_method(rb_vm_top_self(), “public”, top_public,
-1);
rb_define_singleton_method(rb_vm_top_self(), “private”,
top_private, -1);
–
Yusuke E. [email protected]