Bug #18292
closed3.1.0-dev `include` cause Module to be marked as initialized
Description
Some subtle change I found while testing our app compatibility with Ruby head:
class Mod1 < Module
def initialize(...)
super
end
end
p Mod1.new
class Mod2 < Module
def initialize(...)
include Enumerable
super
end
end
p Mod2.new
On 3.0:
#<Mod1:0x00007fbf9b825b38>
#<Mod2:0x00007fbf9b825818>
On ruby-head:
#<Mod1:0x00000001108cb1d8>
/tmp/module.rb:11:in `initialize': already initialized module (TypeError)
from /tmp/module.rb:11:in `initialize'
I suspect this might be a result of https://bugs.ruby-lang.org/issues/17048, but I have to admit I'm not certain so I'd rather report it.
Updated by byroot (Jean Boussier) about 3 years ago
- ruby -v set to ruby 3.1.0dev (2021-11-08T09:35:22Z master 7cc4e147fc)
Updated by jeremyevans0 (Jeremy Evans) almost 3 years ago
A simple work around for this is to include
after calling super
.
initialize
checks whether the module is uninitialized, and fails otherwise. When calling include
, the module is marked as initialized. If you call include
before super
, then the module is initialized before initialize
is called, resulting in an error.
I'm not sure why this check in initialize
is needed. initialize
only does the equivalent of module_exec
if a block is passed. I think it's possible to rearrange the code to fix this. I submitted a pull request for this change: https://github.com/ruby/ruby/pull/5398
Updated by jeremyevans (Jeremy Evans) almost 3 years ago
- Status changed from Open to Closed
Applied in changeset git|a79c59472df38297c246b27713c277f2edaefa7a.
Allow include before calling Module#initialize
This is to allow Module subclasses that include modules before
calling super in the subclass's initialize.
Remove rb_module_check_initializable from Module#initialize.
Module#initialize only calls module_exec if a block is passed,
it doesn't have other issues that would cause problems if
called multiple times or with an already initialized module.
Move initialization of super to Module#allocate, though I'm not
sure it is required there. However, it's needed to be removed
from Module#initialize for this to work.
Fixes [Bug #18292]
Updated by byroot (Jean Boussier) almost 3 years ago
@jeremyevans thanks for the fix. Do you think we should mark this as a 3.1 backport?
Updated by jeremyevans0 (Jeremy Evans) almost 3 years ago
- Backport changed from 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN to 2.6: DONTNEED, 2.7: DONTNEED, 3.0: DONTNEED, 3.1: REQUIRED
byroot (Jean Boussier) wrote in #note-4:
@jeremyevans thanks for the fix. Do you think we should mark this as a 3.1 backport?
Sure, that makes sense to me.
Updated by naruse (Yui NARUSE) almost 3 years ago
- Backport changed from 2.6: DONTNEED, 2.7: DONTNEED, 3.0: DONTNEED, 3.1: REQUIRED to 2.6: DONTNEED, 2.7: DONTNEED, 3.0: DONTNEED, 3.1: DONE
ruby_3_1 28ec24db4a8201fa624692cdc1cbef9b00489412 merged revision(s) a79c59472df38297c246b27713c277f2edaefa7a.