diff options
author | Jeremy Evans <[email protected]> | 2020-01-06 16:41:03 -0800 |
---|---|---|
committer | Jeremy Evans <[email protected]> | 2020-02-27 11:03:13 -0800 |
commit | 3556a834a2847e52162d1d3302d4c64390df1694 (patch) | |
tree | 400bb182c86b19d14a777828fb07622c831d6625 /class.c | |
parent | 1ca3a22117fb646579773960247aa46db46cb03c (diff) |
Make Module#include affect the iclasses of the module
When calling Module#include, if the receiver is a module,
walk the subclasses list and include the argument module in each
iclass.
This does not affect Module#prepend, as fixing that is significantly
more involved.
Fixes [Bug #9573]
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/2936
Diffstat (limited to 'class.c')
-rw-r--r-- | class.c | 20 |
1 files changed, 20 insertions, 0 deletions
@@ -883,6 +883,26 @@ rb_include_module(VALUE klass, VALUE module) changed = include_modules_at(klass, RCLASS_ORIGIN(klass), module, TRUE); if (changed < 0) rb_raise(rb_eArgError, "cyclic include detected"); + + if (RB_TYPE_P(klass, T_MODULE)) { + rb_subclass_entry_t *iclass = RCLASS_EXT(klass)->subclasses; + int do_include = 1; + while (iclass) { + VALUE check_class = iclass->klass; + while (check_class) { + if (RB_TYPE_P(check_class, T_ICLASS) && + (RBASIC(check_class)->klass == module)) { + do_include = 0; + } + check_class = RCLASS_SUPER(check_class); + } + + if (do_include) { + include_modules_at(iclass->klass, RCLASS_ORIGIN(iclass->klass), module, TRUE); + } + iclass = iclass->next; + } + } } static enum rb_id_table_iterator_result |