This uses the superclass table recently introduced to implement fast
inheritance checking between classes (ex. Foo < Bar).

This is almost identical to what we do in class_search_class_ancestor
(as called by rb_obj_is_kind_of) except that we are checking both
directions: ie. both whether Foo < Bar and whether Bar < Foo.
This commit is contained in:
John Hawthorn 2022-03-05 13:03:33 -08:00
Родитель 7aabdbe837
Коммит d76ba1c219
1 изменённых файлов: 31 добавлений и 10 удалений

Просмотреть файл

@ -1633,17 +1633,38 @@ VALUE
rb_class_inherited_p(VALUE mod, VALUE arg)
{
if (mod == arg) return Qtrue;
if (!CLASS_OR_MODULE_P(arg) && !RB_TYPE_P(arg, T_ICLASS)) {
rb_raise(rb_eTypeError, "compared with non class/module");
if (RB_TYPE_P(arg, T_CLASS) && RB_TYPE_P(mod, T_CLASS)) {
// comparison between classes
size_t mod_depth = RCLASS_SUPERCLASS_DEPTH(mod);
size_t arg_depth = RCLASS_SUPERCLASS_DEPTH(arg);
if (arg_depth < mod_depth) {
// check if mod < arg
return RCLASS_SUPERCLASSES(mod)[arg_depth] == arg ?
Qtrue :
Qnil;
} else if (arg_depth > mod_depth) {
// check if mod > arg
return RCLASS_SUPERCLASSES(arg)[mod_depth] == mod ?
Qfalse :
Qnil;
} else {
// Depths match, and we know they aren't equal: no relation
return Qnil;
}
} else {
if (!CLASS_OR_MODULE_P(arg) && !RB_TYPE_P(arg, T_ICLASS)) {
rb_raise(rb_eTypeError, "compared with non class/module");
}
if (class_search_ancestor(mod, RCLASS_ORIGIN(arg))) {
return Qtrue;
}
/* not mod < arg; check if mod > arg */
if (class_search_ancestor(arg, mod)) {
return Qfalse;
}
return Qnil;
}
if (class_search_ancestor(mod, RCLASS_ORIGIN(arg))) {
return Qtrue;
}
/* not mod < arg; check if mod > arg */
if (class_search_ancestor(arg, mod)) {
return Qfalse;
}
return Qnil;
}
/*