Project

General

Profile

Bug #15629 ยป super_method-bind-unbind-clone-15629.patch

jeremyevans0 (Jeremy Evans), 10/02/2019 10:23 PM

View differences:

proc.c
&method_data_type, data);
RB_OBJ_WRITE(method, &data->recv, Qundef);
RB_OBJ_WRITE(method, &data->klass, orig->klass);
RB_OBJ_WRITE(method, &data->iclass, orig->iclass);
RB_OBJ_WRITE(method, &data->me, rb_method_entry_clone(orig->me));
OBJ_INFECT(method, obj);
......
CLONESETUP(clone, self);
RB_OBJ_WRITE(clone, &data->recv, orig->recv);
RB_OBJ_WRITE(clone, &data->klass, orig->klass);
RB_OBJ_WRITE(clone, &data->iclass, orig->iclass);
RB_OBJ_WRITE(clone, &data->me, rb_method_entry_clone(orig->me));
return clone;
}
......
*/
static void
convert_umethod_to_method_components(VALUE method, VALUE recv, VALUE *methclass_out, VALUE *klass_out, const rb_method_entry_t **me_out)
convert_umethod_to_method_components(VALUE method, VALUE recv, VALUE *methclass_out, VALUE *klass_out, VALUE *iclass_out, const rb_method_entry_t **me_out)
{
struct METHOD *data;
TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
VALUE methclass = data->me->owner;
VALUE iclass = data->me->defined_class;
VALUE klass = CLASS_OF(recv);
if (!RB_TYPE_P(methclass, T_MODULE) &&
......
VALUE ic = rb_class_search_ancestor(klass, me->owner);
if (ic) {
klass = ic;
iclass = ic;
}
else {
klass = rb_include_class_new(methclass, klass);
......
*methclass_out = methclass;
*klass_out = klass;
*iclass_out = iclass;
*me_out = me;
}
......
static VALUE
umethod_bind(VALUE method, VALUE recv)
{
VALUE methclass, klass;
VALUE methclass, klass, iclass;
const rb_method_entry_t *me;
convert_umethod_to_method_components(method, recv, &methclass, &klass, &me);
convert_umethod_to_method_components(method, recv, &methclass, &klass, &iclass, &me);
struct METHOD *bound;
method = TypedData_Make_Struct(rb_cMethod, struct METHOD, &method_data_type, bound);
RB_OBJ_WRITE(method, &bound->recv, recv);
RB_OBJ_WRITE(method, &bound->klass, klass);
RB_OBJ_WRITE(method, &bound->iclass, iclass);
RB_OBJ_WRITE(method, &bound->me, me);
return method;
......
argc--;
argv++;
VALUE methclass, klass;
VALUE methclass, klass, iclass;
const rb_method_entry_t *me;
convert_umethod_to_method_components(method, recv, &methclass, &klass, &me);
convert_umethod_to_method_components(method, recv, &methclass, &klass, &iclass, &me);
struct METHOD bound = { recv, klass, 0, me };
VALUE passed_procval = rb_block_given_p() ? rb_block_proc() : Qnil;
test/ruby/test_method.rb
assert_nil(m.super_method)
end
def test_super_method_bind_unbind_clone
bug15629_m1 = Module.new do
def foo; end
end
bug15629_m2 = Module.new do
def foo; end
end
bug15629_c = Class.new do
include bug15629_m1
include bug15629_m2
end
o = bug15629_c.new
m = o.:foo
sm = m.super_method
im = bug15629_c.instance_method(:foo)
sim = im.super_method
assert_equal(sm, m.clone.super_method)
assert_equal(sim, m.unbind.super_method)
assert_equal(sim, m.unbind.clone.super_method)
assert_equal(sim, im.clone.super_method)
assert_equal(sm, m.unbind.bind(o).super_method)
assert_equal(sm, m.unbind.clone.bind(o).super_method)
assert_equal(sm, im.bind(o).super_method)
assert_equal(sm, im.clone.bind(o).super_method)
end
def test_super_method_removed
c1 = Class.new {private def foo; end}
c2 = Class.new(c1) {public :foo}
    (1-1/1)