summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc-Andre Lafortune <github@marc-andre.ca>2020-09-01 21:22:20 -0400
committerMarc-André Lafortune <github@marc-andre.ca>2020-09-02 00:05:14 -0400
commit5e16857315bf55307c5fc887ca6f03bfa0630a93 (patch)
treed42bcc39f4cdfb958d620f3d1389f2aa677b77cb
parent11922b5e030808b16fd2c604637e046b2d01b0f0 (diff)
Fix constant names set using const_set on a singleton class
Fixes [Bug #14895]
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/3502
-rw-r--r--spec/ruby/core/module/const_set_spec.rb18
-rw-r--r--spec/ruby/core/module/name_spec.rb18
-rw-r--r--spec/ruby/language/module_spec.rb18
-rw-r--r--test/ruby/test_module.rb10
-rw-r--r--variable.c17
5 files changed, 59 insertions, 22 deletions
diff --git a/spec/ruby/core/module/const_set_spec.rb b/spec/ruby/core/module/const_set_spec.rb
index 77a2e59a13..b537d3f133 100644
--- a/spec/ruby/core/module/const_set_spec.rb
+++ b/spec/ruby/core/module/const_set_spec.rb
@@ -20,10 +20,20 @@ describe "Module#const_set" do
m.name.should == "ConstantSpecs::CS_CONST1000"
end
- it "does not set the name of a module scoped by an anonymous module" do
- a, b = Module.new, Module.new
- a.const_set :B, b
- b.name.should be_nil
+ ruby_version_is ""..."3.0" do
+ it "does not set the name of a module scoped by an anonymous module" do
+ a, b = Module.new, Module.new
+ a.const_set :B, b
+ b.name.should be_nil
+ end
+ end
+
+ ruby_version_is "3.0" do
+ it "sets the name of a module scoped by an anonymous module" do
+ a, b = Module.new, Module.new
+ a.const_set :B, b
+ b.name.should.end_with? '::B'
+ end
end
it "sets the name of contained modules when assigning a toplevel anonymous module" do
diff --git a/spec/ruby/core/module/name_spec.rb b/spec/ruby/core/module/name_spec.rb
index ae8037555b..ca9106a973 100644
--- a/spec/ruby/core/module/name_spec.rb
+++ b/spec/ruby/core/module/name_spec.rb
@@ -6,10 +6,20 @@ describe "Module#name" do
Module.new.name.should be_nil
end
- it "is nil when assigned to a constant in an anonymous module" do
- m = Module.new
- m::N = Module.new
- m::N.name.should be_nil
+ ruby_version_is ""..."3.0" do
+ it "is nil when assigned to a constant in an anonymous module" do
+ m = Module.new
+ m::N = Module.new
+ m::N.name.should be_nil
+ end
+ end
+
+ ruby_version_is "3.0" do
+ it "is not nil when assigned to a constant in an anonymous module" do
+ m = Module.new
+ m::N = Module.new
+ m::N.name.should.end_with? '::N'
+ end
end
it "is not nil for a nested module created with the module keyword" do
diff --git a/spec/ruby/language/module_spec.rb b/spec/ruby/language/module_spec.rb
index 1b41e184bb..cbc7149359 100644
--- a/spec/ruby/language/module_spec.rb
+++ b/spec/ruby/language/module_spec.rb
@@ -69,10 +69,20 @@ describe "Assigning an anonymous module to a constant" do
mod.name.should == "ModuleSpecs_CS1"
end
- it "does not set the name of a module scoped by an anonymous module" do
- a, b = Module.new, Module.new
- a::B = b
- b.name.should be_nil
+ ruby_version_is ""..."3.0" do
+ it "does not set the name of a module scoped by an anonymous module" do
+ a, b = Module.new, Module.new
+ a::B = b
+ b.name.should be_nil
+ end
+ end
+
+ ruby_version_is "3.0" do
+ it "sets the name of a module scoped by an anonymous module" do
+ a, b = Module.new, Module.new
+ a::B = b
+ b.name.should.end_with? '::B'
+ end
end
it "sets the name of contained modules when assigning a toplevel anonymous module" do
diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb
index d2da384cbd..94e415b08c 100644
--- a/test/ruby/test_module.rb
+++ b/test/ruby/test_module.rb
@@ -767,13 +767,13 @@ class TestModule < Test::Unit::TestCase
n = Module.new
m.const_set(:N, n)
assert_nil(m.name)
- assert_nil(n.name)
+ assert_match(/::N$/, n.name)
assert_equal([:N], m.constants)
m.module_eval("module O end")
assert_equal([:N, :O], m.constants.sort)
m.module_eval("class C; end")
assert_equal([:C, :N, :O], m.constants.sort)
- assert_nil(m::N.name)
+ assert_match(/::N$/, m::N.name)
assert_match(/\A#<Module:.*>::O\z/, m::O.name)
assert_match(/\A#<Module:.*>::C\z/, m::C.name)
self.class.const_set(:M, m)
@@ -2724,6 +2724,12 @@ class TestModule < Test::Unit::TestCase
assert_not_predicate m.clone(freeze: false), :frozen?
end
+ def test_module_name_in_singleton_method
+ s = Object.new.singleton_class
+ mod = s.const_set(:Foo, Module.new)
+ assert_match(/::Foo$/, mod.name, '[Bug #14895]')
+ end
+
private
def assert_top_method_is_private(method)
diff --git a/variable.c b/variable.c
index 26928ca0bc..3c3b689889 100644
--- a/variable.c
+++ b/variable.c
@@ -2854,14 +2854,15 @@ rb_const_set(VALUE klass, ID id, VALUE val)
else {
int parental_path_permanent;
VALUE parental_path = classname(klass, &parental_path_permanent);
- if (!NIL_P(parental_path)) {
- if (parental_path_permanent && !val_path_permanent) {
- set_namespace_path(val, build_const_path(parental_path, id));
- }
- else if (!parental_path_permanent && NIL_P(val_path)) {
- rb_ivar_set(val, tmp_classpath, build_const_path(parental_path, id));
- }
- }
+ if (NIL_P(parental_path)) {
+ parental_path = rb_funcall(klass, rb_intern("to_s"), 0);
+ }
+ if (parental_path_permanent && !val_path_permanent) {
+ set_namespace_path(val, build_const_path(parental_path, id));
+ }
+ else if (!parental_path_permanent && NIL_P(val_path)) {
+ rb_ivar_set(val, tmp_classpath, build_const_path(parental_path, id));
+ }
}
}
}