diff options
author | Jeremy Evans <[email protected]> | 2021-02-09 15:39:34 -0800 |
---|---|---|
committer | Jeremy Evans <[email protected]> | 2021-02-11 07:45:52 -0800 |
commit | 2d877327e12f499ac1a0d7096f4314cc92ef228e (patch) | |
tree | e20d0748b139036111a0d9c0c6f1cbb2606576fd /class.c | |
parent | b83ad02997dfa910c08dd2d900f24468c15db264 (diff) |
Make a cyclic prepend not modify ancestors for the receiver
Check for cyclic prepend before making any changes. This requires
scanning the module ancestor chain twice, but in general modules
do not have large numbers of ancestors.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/4165
Diffstat (limited to 'class.c')
-rw-r--r-- | class.c | 14 |
1 files changed, 12 insertions, 2 deletions
@@ -1024,6 +1024,18 @@ include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super) struct rb_id_table *const klass_m_tbl = RCLASS_M_TBL(klass_origin); VALUE original_klass = klass; + if (klass_m_tbl) { + VALUE original_module = module; + + while (module) { + if (klass_m_tbl == RCLASS_M_TBL(module)) + return -1; + module = RCLASS_SUPER(module); + } + + module = original_module; + } + while (module) { int c_seen = FALSE; int superclass_seen = FALSE; @@ -1032,8 +1044,6 @@ include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super) if (klass == c) { c_seen = TRUE; } - if (klass_m_tbl && klass_m_tbl == RCLASS_M_TBL(module)) - return -1; if (klass_origin != c || search_super) { /* ignore if the module included already in superclasses for include, * ignore if the module included before origin class for prepend |