diff options
-rw-r--r-- | internal.h | 1 | ||||
-rw-r--r-- | object.c | 32 |
2 files changed, 22 insertions, 11 deletions
diff --git a/internal.h b/internal.h index fc17da98d5..36424437f9 100644 --- a/internal.h +++ b/internal.h @@ -715,6 +715,7 @@ rb_float_new_inline(double d) /* object.c */ VALUE rb_obj_equal(VALUE obj1, VALUE obj2); +VALUE rb_class_search_ancestor(VALUE klass, VALUE super); struct RBasicRaw { VALUE flags; @@ -587,6 +587,8 @@ class_or_module_required(VALUE c) return c; } +static VALUE class_search_ancestor(VALUE cl, VALUE c); + /* * call-seq: * obj.instance_of?(class) -> true or false @@ -647,15 +649,27 @@ rb_obj_is_kind_of(VALUE obj, VALUE c) VALUE cl = CLASS_OF(obj); c = class_or_module_required(c); - c = RCLASS_ORIGIN(c); + return class_search_ancestor(cl, RCLASS_ORIGIN(c)) ? Qtrue : Qfalse; +} + +static VALUE +class_search_ancestor(VALUE cl, VALUE c) +{ while (cl) { if (cl == c || RCLASS_M_TBL_WRAPPER(cl) == RCLASS_M_TBL_WRAPPER(c)) - return Qtrue; + return cl; cl = RCLASS_SUPER(cl); } - return Qfalse; + return 0; } +VALUE +rb_class_search_ancestor(VALUE cl, VALUE c) +{ + cl = class_or_module_required(cl); + c = class_or_module_required(c); + return class_search_ancestor(cl, RCLASS_ORIGIN(c)); +} /* * call-seq: @@ -1554,16 +1568,12 @@ rb_class_inherited_p(VALUE mod, VALUE arg) rb_raise(rb_eTypeError, "compared with non class/module"); } arg = RCLASS_ORIGIN(arg); - while (mod) { - if (RCLASS_M_TBL_WRAPPER(mod) == RCLASS_M_TBL_WRAPPER(arg)) - return Qtrue; - mod = RCLASS_SUPER(mod); + if (class_search_ancestor(mod, arg)) { + return Qtrue; } /* not mod < arg; check if mod > arg */ - while (arg) { - if (RCLASS_M_TBL_WRAPPER(arg) == RCLASS_M_TBL_WRAPPER(start)) - return Qfalse; - arg = RCLASS_SUPER(arg); + if (class_search_ancestor(arg, start)) { + return Qfalse; } return Qnil; } |