Skip to content

Commit 9a88834

Browse files
committed
There is no need to invalidate methods in moduleNotClass.include/prepend(module)
1 parent e88a888 commit 9a88834

File tree

1 file changed

+16
-10
lines changed

1 file changed

+16
-10
lines changed

src/main/java/org/truffleruby/core/module/ModuleFields.java

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -313,10 +313,12 @@ private void performIncludes(ModuleChain inclusionPoint, Deque<RubyModule> modul
313313
while (!moduleAncestors.isEmpty()) {
314314
RubyModule toInclude = moduleAncestors.pop();
315315
inclusionPoint.insertAfter(toInclude);
316-
toInclude.fields.includedBy.add(rubyModule);
317-
// Module#include only adds modules between the current class and the super class,
318-
// so invalidating the current class is enough as all affected lookups would go through the current class.
319-
newMethodsVersion(toInclude.fields.getMethodNames());
316+
if (rubyModule instanceof RubyClass) { // M.include(N) just registers N but does nothing until C.include/prepend(M)
317+
toInclude.fields.includedBy.add(rubyModule);
318+
// Module#include only adds modules between the current class and the super class,
319+
// so invalidating the current class is enough as all affected lookups would go through the current class.
320+
newMethodsVersion(toInclude.fields.getMethodNames());
321+
}
320322
}
321323
}
322324

@@ -346,7 +348,9 @@ public void prepend(RubyContext context, Node currentNode, RubyModule module) {
346348

347349
/* We need to invalidate all prepended modules and the class, because call sites which looked up methods before
348350
* only check the class or one of the prepend module (if the method is defined there). */
349-
final List<RubyModule> prependedModulesAndSelf = getPrependedModulesAndSelf();
351+
final List<RubyModule> prependedModulesAndClass = rubyModule instanceof RubyClass
352+
? getPrependedModulesAndClass()
353+
: null;
350354

351355
ModuleChain mod = module.fields.start;
352356
ModuleChain cur = start;
@@ -356,10 +360,12 @@ public void prepend(RubyContext context, Node currentNode, RubyModule module) {
356360
final RubyModule toPrepend = mod.getActualModule();
357361
if (!ModuleOperations.includesModule(rubyModule, toPrepend)) {
358362
cur.insertAfter(toPrepend);
359-
final List<String> methodsToInvalidate = toPrepend.fields.getMethodNames();
360-
for (RubyModule moduleToInvalidate : prependedModulesAndSelf) {
361-
toPrepend.fields.includedBy.add(moduleToInvalidate);
362-
moduleToInvalidate.fields.newMethodsVersion(methodsToInvalidate);
363+
if (rubyModule instanceof RubyClass) { // M.prepend(N) just registers N but does nothing until C.prepend/include(M)
364+
final List<String> methodsToInvalidate = toPrepend.fields.getMethodNames();
365+
for (RubyModule moduleToInvalidate : prependedModulesAndClass) {
366+
toPrepend.fields.includedBy.add(moduleToInvalidate);
367+
moduleToInvalidate.fields.newMethodsVersion(methodsToInvalidate);
368+
}
363369
}
364370
cur = cur.getParentModule();
365371
}
@@ -373,7 +379,7 @@ public void prepend(RubyContext context, Node currentNode, RubyModule module) {
373379
invalidateBuiltinsAssumptions();
374380
}
375381

376-
private List<RubyModule> getPrependedModulesAndSelf() {
382+
private List<RubyModule> getPrependedModulesAndClass() {
377383
final List<RubyModule> prependedModulesAndClass = new ArrayList<>();
378384
ModuleChain chain = getFirstModuleChain();
379385
while (chain != this) {

0 commit comments

Comments
 (0)