summaryrefslogtreecommitdiff
path: root/proc.c
diff options
context:
space:
mode:
authorKoichi Sasada <ko1@atdot.net>2022-12-03 05:55:33 +0900
committerKoichi Sasada <ko1@atdot.net>2022-12-03 08:53:12 +0900
commit59e389af2893c0fcf8b2cfa008c9a16825bf56ff (patch)
tree31224e3498843912e2fc8734710e03224aaca21c /proc.c
parent7161bf34e161979b97dbc0c1f7450c195faffcfe (diff)
downloadruby-59e389af2893c0fcf8b2cfa008c9a16825bf56ff.tar.gz
UnboundMethod only refer defined_class
UnboundMethod records caller's class, like `D` or `E` on the following case: ```ruby class C def foo = :foo end class D < C end class E < C end d = D.instance_method(:foo) e = E.instance_method(:foo) ``` But `d` and `e` only refers `C#foo` so that UnboundMethod doesn't record `D` or `E`. This behavior changes the following methods: * `UnboundMethod#inspect` (doesn't show caller's class) * `UnboundMethod#==` (`d == e` for example) fix https://bugs.ruby-lang.org/issues/18798
Diffstat (limited to 'proc.c')
-rw-r--r--proc.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/proc.c b/proc.c
index 71b6f1ef80..e4762db494 100644
--- a/proc.c
+++ b/proc.c
@@ -1724,8 +1724,14 @@ mnew_internal(const rb_method_entry_t *me, VALUE klass, VALUE iclass,
method = TypedData_Make_Struct(mclass, struct METHOD, &method_data_type, data);
- RB_OBJ_WRITE(method, &data->recv, obj);
- RB_OBJ_WRITE(method, &data->klass, klass);
+ if (obj == Qundef) {
+ RB_OBJ_WRITE(method, &data->recv, Qundef);
+ RB_OBJ_WRITE(method, &data->klass, Qundef);
+ }
+ else {
+ RB_OBJ_WRITE(method, &data->recv, obj);
+ RB_OBJ_WRITE(method, &data->klass, klass);
+ }
RB_OBJ_WRITE(method, &data->iclass, iclass);
RB_OBJ_WRITE(method, &data->owner, original_me->owner);
RB_OBJ_WRITE(method, &data->me, me);
@@ -1876,9 +1882,9 @@ method_unbind(VALUE obj)
method = TypedData_Make_Struct(rb_cUnboundMethod, struct METHOD,
&method_data_type, data);
RB_OBJ_WRITE(method, &data->recv, Qundef);
- RB_OBJ_WRITE(method, &data->klass, orig->klass);
+ RB_OBJ_WRITE(method, &data->klass, Qundef);
RB_OBJ_WRITE(method, &data->iclass, orig->iclass);
- RB_OBJ_WRITE(method, &data->owner, orig->owner);
+ RB_OBJ_WRITE(method, &data->owner, orig->me->owner);
RB_OBJ_WRITE(method, &data->me, rb_method_entry_clone(orig->me));
return method;
@@ -3139,7 +3145,11 @@ method_inspect(VALUE method)
defined_class = RBASIC_CLASS(defined_class);
}
- if (FL_TEST(mklass, FL_SINGLETON)) {
+ if (data->recv == Qundef) {
+ // UnboundMethod
+ rb_str_buf_append(str, rb_inspect(defined_class));
+ }
+ else if (FL_TEST(mklass, FL_SINGLETON)) {
VALUE v = rb_ivar_get(mklass, attached);
if (UNDEF_P(data->recv)) {