error.c: Update the message format for NoMethodError

* If the receiver is a Class, use "... for class <class name>".
* If the receiver is a Module, use "... for module <module name>".
* If the receiver is an extended object (i.e., has a singleton class),
  use "... for <rb_any_to_s(receiver)>".
* Otherwise, use "... for an instance of <class name>".

Examples:

```
42.time    #=> undefined method `time' for an instance of Integer (NoMethodError)

class Foo
  privatee #=> undefined local variable or method 'privatee' for class Foo (NoMethodError)
end

def (o=Object.new).foo
end
o.bar      #=> undefined method `bar' for #<Object: 0xdeadbeef(any_to_s)> (NoMethodError)
```
This commit is contained in:
Yusuke Endoh 2023-01-24 17:40:57 +09:00
parent e7b8d32e16
commit 1fd181b453
Notes: git 2023-02-20 01:33:36 +00:00

View File

@ -2116,12 +2116,14 @@ name_err_mesg_to_str(VALUE obj)
object:
klass = CLASS_OF(obj);
if (RB_TYPE_P(klass, T_CLASS) && FL_TEST(klass, FL_SINGLETON)) {
s = FAKE_CSTR(&s_str, "extended object ");
s = FAKE_CSTR(&s_str, "");
c = rb_any_to_s(obj);
break;
}
else {
s = FAKE_CSTR(&s_str, "object ");
s = FAKE_CSTR(&s_str, "an instance of ");
c = rb_class_real(klass);
}
c = rb_class_real(klass);
}
c2 = rb_protect(name_err_mesg_receiver_name, c, &state);
if (state || NIL_OR_UNDEF_P(c2))