diff options
author | Jean Boussier <jean.boussier@gmail.com> | 2020-05-04 16:56:45 +0200 |
---|---|---|
committer | Nobuyoshi Nakada <nobu@ruby-lang.org> | 2020-05-26 14:10:33 +0900 |
commit | 385ac07fd8f5a50825aee8db459086e617f492aa (patch) | |
tree | fc1d12126f2f04cb5032e9e7329157dabb6ef6d6 | |
parent | 4e1f2283b432e833bd4e6f7724ba0496760e68e8 (diff) |
Use receiver #name rather than #inspect to build NameError message
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/3080
-rw-r--r-- | error.c | 15 | ||||
-rw-r--r-- | spec/ruby/language/constants_spec.rb | 30 |
2 files changed, 44 insertions, 1 deletions
@@ -1763,6 +1763,17 @@ name_err_mesg_equal(VALUE obj1, VALUE obj2) /* :nodoc: */ static VALUE +name_err_mesg_receiver_name(VALUE obj) +{ + if (RB_SPECIAL_CONST_P(obj)) return Qundef; + if (RB_BUILTIN_TYPE(obj) == T_MODULE || RB_BUILTIN_TYPE(obj) == T_CLASS) { + return rb_check_funcall(obj, rb_intern("name"), 0, 0); + } + return Qundef; +} + +/* :nodoc: */ +static VALUE name_err_mesg_to_str(VALUE obj) { VALUE *ptr, mesg; @@ -1789,7 +1800,9 @@ name_err_mesg_to_str(VALUE obj) d = FAKE_CSTR(&d_str, "false"); break; default: - d = rb_protect(rb_inspect, obj, &state); + d = rb_protect(name_err_mesg_receiver_name, obj, &state); + if (state || d == Qundef || d == Qnil) + d = rb_protect(rb_inspect, obj, &state); if (state) rb_set_errinfo(Qnil); if (NIL_P(d)) { diff --git a/spec/ruby/language/constants_spec.rb b/spec/ruby/language/constants_spec.rb index 95b0dcace9..47897234b9 100644 --- a/spec/ruby/language/constants_spec.rb +++ b/spec/ruby/language/constants_spec.rb @@ -154,6 +154,36 @@ describe "Literal (A::X) constant resolution" do -> { ConstantSpecs::ParentA::CS_CONSTX }.should raise_error(NameError) end + ruby_version_is "2.8" do + it "uses the module or class #name to craft the error message" do + mod = Module.new do + def self.name + "ModuleName" + end + + def self.inspect + "<unusable info>" + end + end + + -> { mod::DOES_NOT_EXIST }.should raise_error(NameError, /uninitialized constant ModuleName::DOES_NOT_EXIST/) + end + + it "uses the module or class #inspect to craft the error message if they are anonymous" do + mod = Module.new do + def self.name + nil + end + + def self.inspect + "<unusable info>" + end + end + + -> { mod::DOES_NOT_EXIST }.should raise_error(NameError, /uninitialized constant <unusable info>::DOES_NOT_EXIST/) + end + end + it "sends #const_missing to the original class or module scope" do ConstantSpecs::ClassA::CS_CONSTX.should == :CS_CONSTX end |