diff options
author | Yusuke Endoh <[email protected]> | 2022-12-16 07:31:27 +0900 |
---|---|---|
committer | Yusuke Endoh <[email protected]> | 2023-02-20 10:33:06 +0900 |
commit | e7b8d32e166815f2e7edebf32aa178915d191b8c (patch) | |
tree | 94f8b15c9d5644886c545404756f68dcf37d4eff /error.c | |
parent | 5c0298bf181921a8aa63cd250d67b294cfe90322 (diff) |
Stop using receiver#inspect for "undefined method" errors
```
42.time #=> undefined method `time' for object Integer (NoMethodError)
class Foo
privatee #=> undefined local variable or method 'privatee' for class Foo (NoMethodError)
end
s = ""
def s.foo = nil
s.bar #=> undefined method `bar' for extended object String (NoMethodError)
```
[Feature #18285]
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/6950
Diffstat (limited to 'error.c')
-rw-r--r-- | error.c | 71 |
1 files changed, 52 insertions, 19 deletions
@@ -2066,43 +2066,76 @@ name_err_mesg_to_str(VALUE obj) if (NIL_P(mesg)) return Qnil; else { struct RString s_str, d_str; - VALUE c, s, d = 0, args[4]; - int state = 0, singleton = 0; + VALUE c, s, d = 0, args[4], c2; + int state = 0; rb_encoding *usascii = rb_usascii_encoding(); #define FAKE_CSTR(v, str) rb_setup_fake_str((v), (str), rb_strlen_lit(str), usascii) + c = s = FAKE_CSTR(&s_str, ""); obj = ptr[NAME_ERR_MESG__RECV]; switch (obj) { case Qnil: - d = FAKE_CSTR(&d_str, "nil"); + c = d = FAKE_CSTR(&d_str, "nil"); break; case Qtrue: - d = FAKE_CSTR(&d_str, "true"); + c = d = FAKE_CSTR(&d_str, "true"); break; case Qfalse: - d = FAKE_CSTR(&d_str, "false"); + c = d = FAKE_CSTR(&d_str, "false"); break; default: - d = rb_protect(name_err_mesg_receiver_name, obj, &state); - if (state || NIL_OR_UNDEF_P(d)) - d = rb_protect(rb_inspect, obj, &state); + if (strstr(RSTRING_PTR(mesg), "%2$s")) { + d = rb_protect(name_err_mesg_receiver_name, obj, &state); + if (state || NIL_OR_UNDEF_P(d)) + d = rb_protect(rb_inspect, obj, &state); + if (state) { + rb_set_errinfo(Qnil); + } + d = rb_check_string_type(d); + if (NIL_P(d)) { + d = rb_any_to_s(obj); + } + } + + if (!RB_SPECIAL_CONST_P(obj)) { + switch (RB_BUILTIN_TYPE(obj)) { + case T_MODULE: + s = FAKE_CSTR(&s_str, "module "); + c = obj; + break; + case T_CLASS: + s = FAKE_CSTR(&s_str, "class "); + c = obj; + break; + default: + goto object; + } + } + else { + VALUE klass; +object: + klass = CLASS_OF(obj); + if (RB_TYPE_P(klass, T_CLASS) && FL_TEST(klass, FL_SINGLETON)) { + s = FAKE_CSTR(&s_str, "extended object "); + } + else { + s = FAKE_CSTR(&s_str, "object "); + } + c = rb_class_real(klass); + } + c2 = rb_protect(name_err_mesg_receiver_name, c, &state); + if (state || NIL_OR_UNDEF_P(c2)) + c2 = rb_protect(rb_inspect, c, &state); if (state) { rb_set_errinfo(Qnil); } - d = rb_check_string_type(d); - if (NIL_P(d)) { - d = rb_any_to_s(obj); + c2 = rb_check_string_type(c2); + if (NIL_P(c2)) { + c2 = rb_any_to_s(c); } - singleton = (RSTRING_LEN(d) > 0 && RSTRING_PTR(d)[0] == '#'); + c = c2; break; } - if (!singleton) { - s = FAKE_CSTR(&s_str, ":"); - c = rb_class_name(CLASS_OF(obj)); - } - else { - c = s = FAKE_CSTR(&s_str, ""); - } args[0] = rb_obj_as_string(ptr[NAME_ERR_MESG__NAME]); args[1] = d; args[2] = s; |