summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-07-30 05:24:24 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-07-30 05:24:24 +0000
commit83940fc310d45010fe452fcf4f6ffbaba0c3f5d6 (patch)
tree8d370500150868fde259c54214f3ed1a07899794
parent48d7aa4ae93265cef0d824abe7815befdb47235e (diff)
variable.c: tmp_classpath
* variable.c: store anonymous class path in tmp_classpath but not in classpath. [ruby-core:42865][Bug #6078] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36574 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog5
-rw-r--r--test/ruby/test_module.rb17
-rw-r--r--variable.c50
3 files changed, 61 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index d391390ee8..6918975dda 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Mon Jul 30 14:24:20 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * variable.c: store anonymous class path in tmp_classpath but not in
+ classpath. [ruby-core:42865][Bug #6078]
+
Mon Jul 30 13:11:54 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
* configure.in (DLDFLAGS): on Darwin, deprecate -flat_namespace to get
diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb
index b27f9ddd0f..2051617aad 100644
--- a/test/ruby/test_module.rb
+++ b/test/ruby/test_module.rb
@@ -363,6 +363,23 @@ class TestModule < Test::Unit::TestCase
assert_equal("TestModule::User", User.name)
end
+ def test_classpath
+ m = Module.new
+ n = Module.new
+ m.const_set(:N, n)
+ assert_nil(m.name)
+ assert_nil(n.name)
+ assert_equal([:N], m.constants)
+ m.module_eval("module O end")
+ assert_equal([:N, :O], m.constants)
+ assert_nil(m::N.name)
+ assert_match(/\A(?:#<Module:.*>::)?O\z/, m::O.name)
+ self.class.const_set(:M, m)
+ prefix = self.class.name + "::M::"
+ assert_equal(prefix+"N", m.const_get(:N).name)
+ assert_equal(prefix+"O", m.const_get(:O).name)
+ end
+
def test_private_class_method
assert_raise(ExpectedException) { AClass.cm1 }
assert_raise(ExpectedException) { AClass.cm3 }
diff --git a/variable.c b/variable.c
index 078d4d175b..21798d42c8 100644
--- a/variable.c
+++ b/variable.c
@@ -35,7 +35,7 @@ Init_var_tables(void)
}
struct fc_result {
- ID name;
+ ID name, preferred;
VALUE klass;
VALUE path;
VALUE track;
@@ -78,7 +78,7 @@ fc_i(st_data_t k, st_data_t v, st_data_t a)
VALUE value = ce->value;
if (!rb_is_const_id(key)) return ST_CONTINUE;
- if (value == res->klass) {
+ if (value == res->klass && (!res->preferred || key == res->preferred)) {
res->path = fc_path(res, key);
return ST_STOP;
}
@@ -95,6 +95,7 @@ fc_i(st_data_t k, st_data_t v, st_data_t a)
}
arg.name = key;
+ arg.preferred = res->preferred;
arg.path = 0;
arg.klass = res->klass;
arg.track = value;
@@ -110,10 +111,12 @@ fc_i(st_data_t k, st_data_t v, st_data_t a)
}
static VALUE
-find_class_path(VALUE klass)
+find_class_path(VALUE klass, ID preferred)
{
struct fc_result arg;
+ find:
+ arg.preferred = preferred;
arg.name = 0;
arg.path = 0;
arg.klass = klass;
@@ -134,6 +137,10 @@ find_class_path(VALUE klass)
st_delete(RCLASS_IV_TBL(klass), &tmp, 0);
return arg.path;
}
+ if (preferred) {
+ preferred = 0;
+ goto find;
+ }
return Qnil;
}
@@ -147,9 +154,14 @@ classname(VALUE klass)
if (RCLASS_IV_TBL(klass)) {
if (!st_lookup(RCLASS_IV_TBL(klass), (st_data_t)classpath, &n)) {
if (!st_lookup(RCLASS_IV_TBL(klass), (st_data_t)classid, &n)) {
- return find_class_path(klass);
+ return find_class_path(klass, (ID)0);
+ }
+ path = find_class_path(klass, SYM2ID(n));
+ if (NIL_P(path)) {
+ path = rb_str_dup(rb_id2str(SYM2ID((VALUE)n)));
+ OBJ_FREEZE(path);
+ return path;
}
- path = rb_str_dup(rb_id2str(SYM2ID((VALUE)n)));
OBJ_FREEZE(path);
st_insert(RCLASS_IV_TBL(klass), (st_data_t)classpath, (st_data_t)path);
n = classid;
@@ -163,7 +175,7 @@ classname(VALUE klass)
}
return path;
}
- return find_class_path(klass);
+ return find_class_path(klass, (ID)0);
}
/*
@@ -182,15 +194,19 @@ rb_mod_name(VALUE mod)
return path;
}
-VALUE
-rb_class_path(VALUE klass)
+static VALUE
+rb_tmp_class_path(VALUE klass, int *permanent)
{
VALUE path = classname(klass);
st_data_t n = (st_data_t)path;
- if (!NIL_P(path)) return path;
+ if (!NIL_P(path)) {
+ *permanent = 1;
+ return path;
+ }
if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),
(st_data_t)tmp_classpath, &n)) {
+ *permanent = 0;
return (VALUE)n;
}
else {
@@ -207,11 +223,19 @@ rb_class_path(VALUE klass)
path = rb_sprintf("#<%s:%p>", s, (void*)klass);
OBJ_FREEZE(path);
rb_ivar_set(klass, tmp_classpath, path);
+ *permanent = 0;
return path;
}
}
+VALUE
+rb_class_path(VALUE klass)
+{
+ int permanent;
+ return rb_tmp_class_path(klass, &permanent);
+}
+
void
rb_set_class_path_string(VALUE klass, VALUE under, VALUE name)
{
@@ -221,10 +245,12 @@ rb_set_class_path_string(VALUE klass, VALUE under, VALUE name)
str = rb_str_new_frozen(name);
}
else {
- str = rb_str_dup(rb_class_path(under));
+ int permanent;
+ str = rb_str_dup(rb_tmp_class_path(under, &permanent));
rb_str_cat2(str, "::");
rb_str_append(str, name);
OBJ_FREEZE(str);
+ if (!permanent) return;
}
rb_ivar_set(klass, classpath, str);
}
@@ -233,16 +259,18 @@ void
rb_set_class_path(VALUE klass, VALUE under, const char *name)
{
VALUE str;
+ int permanent = 1;
if (under == rb_cObject) {
str = rb_str_new2(name);
}
else {
- str = rb_str_dup(rb_class_path(under));
+ str = rb_str_dup(rb_tmp_class_path(under, &permanent));
rb_str_cat2(str, "::");
rb_str_cat2(str, name);
}
OBJ_FREEZE(str);
+ if (!permanent) return;
rb_ivar_set(klass, classpath, str);
}