Project

General

Profile

Actions

Bug #22257

closed

Prepending a module to an already-included module leaves stale super caches

Bug #22257: Prepending a module to an already-included module leaves stale super caches

Added by eightbitraptor (Matt V-H) 4 days ago. Updated 3 days ago.

Status:
Closed
Assignee:
-
Target version:
[ruby-core:<unknown>]

Description

When a module is prepended to a module that already has includers, super call sites inside the prepended module keep calling the old method entry after the method is redefined.

Fix implemented in this PR

module M; def foo; :m; end; end
class D; include M; end
M.prepend(Module.new { def foo; super; end })
D.new.foo                          # prime the super call-site cache
M.send(:define_method, :foo) { :hooked }
p D.new.foo

I found this while working on an unrelated Ractor issue. But this problem manifests itself for Ractors as follows:

Ractor.new {}
require 'set'
Kernel.send(:define_method, :require) { |f| $hook = f }
require 'set'
p $hook # => nil, the hook never runs

This is because creating the first Ractor prepends an internal RactorRequire wrapper onto Kernel. After the first require primes the cache in the wrapper, redefining Kernel#require silently does nothing.

The linked PR fixes this by registering the backfilled iclass in the module's subclasses list, after the includer walk finishes.

Actions

Also available in: PDF Atom