diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | insns.def | 10 | ||||
-rw-r--r-- | test/ruby/test_module.rb | 14 | ||||
-rw-r--r-- | vm_insnhelper.c | 10 |
4 files changed, 36 insertions, 4 deletions
@@ -1,3 +1,9 @@ +Thu Sep 1 17:31:22 2011 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * insns.def (defineclass), vm_insnhelper.c (vm_get_cvar_base): see + also inherited constants for classes without superclass and + modules. [ruby-core:37698] [Bug #3423] + Thu Sep 1 14:11:16 2011 NAKAMURA Usaku <usa@ruby-lang.org> * test/ruby/test_thread.rb (TestThread#test_no_valid_cfp): skip when @@ -895,6 +895,7 @@ defineclass (VALUE val) { VALUE klass; + int newclass = 1; switch ((int)define_type) { case 0: /* scoped: class Foo::Bar */ @@ -903,15 +904,16 @@ defineclass if (super == Qnil) { super = rb_cObject; + newclass = 0; } vm_check_if_namespace(cbase); /* find klass */ rb_autoload_load(cbase, id); - if (rb_const_defined_at(cbase, id)) { + if (vm_const_defined_at(cbase, id, newclass)) { /* already exist */ - klass = define_type == 0 ? rb_public_const_get(cbase, id) : rb_const_get_at(cbase, id); + klass = define_type == 0 ? rb_public_const_get(cbase, id) : rb_const_get_from(cbase, id); if (TYPE(klass) != T_CLASS) { rb_raise(rb_eTypeError, "%s is not a class", rb_id2name(id)); } @@ -947,8 +949,8 @@ defineclass vm_check_if_namespace(cbase); /* find klass */ - if (rb_const_defined_at(cbase, id)) { - klass = define_type == 2 ? rb_public_const_get(cbase, id) : rb_const_get_at(cbase, id); + if (vm_const_defined_at(cbase, id, 0)) { + klass = define_type == 2 ? rb_public_const_get(cbase, id) : rb_const_get_from(cbase, id); /* already exist */ if (TYPE(klass) != T_MODULE) { rb_raise(rb_eTypeError, "%s is not a module", rb_id2name(id)); diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb index a05e11726c..eb495e280a 100644 --- a/test/ruby/test_module.rb +++ b/test/ruby/test_module.rb @@ -532,6 +532,20 @@ class TestModule < Test::Unit::TestCase INPUT end + def test_const_in_module + bug3423 = '[ruby-core:37698]' + assert_in_out_err([], <<-INPUT, %w[ok], [], bug3423) +module LangModuleSpecInObject + module LangModuleTop + end +end +include LangModuleSpecInObject +module LangModuleTop +end +puts "ok" if LangModuleSpecInObject::LangModuleTop == LangModuleTop +INPUT + end + def test_class_variable_get c = Class.new c.class_eval('@@foo = :foo') diff --git a/vm_insnhelper.c b/vm_insnhelper.c index a35dbb1196..609e620151 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -1252,6 +1252,16 @@ vm_get_cvar_base(NODE *cref) return klass; } +static int +vm_const_defined_at(VALUE cbase, ID id, int newclass) +{ + int ret = rb_const_defined_at(cbase, id); + if (!ret && !newclass) { + while ((cbase = RCLASS_SUPER(cbase)) != 0 && cbase != rb_cObject && + !(ret = rb_const_defined_at(cbase, id))); + } + return ret; +} #ifndef USE_IC_FOR_IVAR #define USE_IC_FOR_IVAR 1 |