Skip to content

Fix prepended module initialize not called for Ruby classes rooted in a Java superclass#9322

Merged
headius merged 2 commits intojruby:jruby-10.0from
jimtng:java-prepend-bug
Mar 23, 2026
Merged

Fix prepended module initialize not called for Ruby classes rooted in a Java superclass#9322
headius merged 2 commits intojruby:jruby-10.0from
jimtng:java-prepend-bug

Conversation

@jimtng
Copy link
Copy Markdown
Contributor

@jimtng jimtng commented Mar 21, 2026

Fix #9321

When a module M is prepended to a Ruby class E that subclasses a Java class, the split constructor protocol only saw M's initialize (the effective method after prepend) and never invoked E's own initialize, producing [:d, :c] instead of the correct [:m, :e, :d, :c].

Root causes:

  • tryInstall used clazz.searchMethod which found M's initialize (via prepend hierarchy) instead of E's, so oldInit was wrong
  • splitInitialized had no way to express two Ruby initializes at the same reified-class level (M wrapping E), only a flat isLateral branch
  • SplitCtorData lacked a clazz field so finishInitialize used getMetaClass() as the defining module, causing incorrect method lookup

Fix:

  • tryInstall now uses clazz.getMethodLocation().searchMethod to capture E's own initialize as oldInit
  • Add findIncludedPrependedModule helper to detect when the found method lives in an included prepend-wrapper for the base class
  • Add isPrependedJavaCtorWrapper to identify this specific structural case
  • In splitInitialized, handle the prepend-wrapper case by splitting M first, recursing into the prepend-wrapper's superclass for E's split, then chaining the two SplitCtorData via a new nested field
  • finishInitialize recurses through nested first, ensuring M->E->D->C order
  • Add clazz field to SplitCtorData so finishInitialize uses the correct defining module for direct (no-state) calls
  • Fix isClassOrIncludedPrependedModule to use getDelegate() comparisons

… a Java superclass

When a module M is prepended to a Ruby class E that subclasses a Java class,
the split constructor protocol only saw M's initialize (the effective method
after prepend) and never invoked E's own initialize, producing [:d, :c]
instead of the correct [:m, :e, :d, :c].

Root causes:
- tryInstall used clazz.searchMethod which found M's initialize (via prepend
  hierarchy) instead of E's, so oldInit was wrong
- splitInitialized had no way to express two Ruby initializes at the same
  reified-class level (M wrapping E), only a flat isLateral branch
- SplitCtorData lacked a clazz field so finishInitialize used getMetaClass()
  as the defining module, causing incorrect method lookup

Fix:
- tryInstall now uses clazz.getMethodLocation().searchMethod to capture E's
  own initialize as oldInit
- Add findIncludedPrependedModule helper to detect when the found method lives
  in an included prepend-wrapper for the base class
- Add isPrependedJavaCtorWrapper to identify this specific structural case
- In splitInitialized, handle the prepend-wrapper case by splitting M first,
  recursing into the prepend-wrapper's superclass for E's split, then chaining
  the two SplitCtorData via a new nested field
- finishInitialize recurses through nested first, ensuring M->E->D->C order
- Add clazz field to SplitCtorData so finishInitialize uses the correct
  defining module for direct (no-state) calls
- Fix isClassOrIncludedPrependedModule to use getDelegate() comparisons
@jimtng jimtng force-pushed the java-prepend-bug branch from bed8c79 to 2f1f0b6 Compare March 21, 2026 06:17
Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>
Copy link
Copy Markdown
Member

@headius headius left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks logical to me. The operative change seems to be using getMethodLocation so that prepends are handled correctly.

@headius headius added this to the JRuby 10.0.5.0 milestone Mar 23, 2026
@headius
Copy link
Copy Markdown
Member

headius commented Mar 23, 2026

@jimtng Thank you for looking into this issue!

@headius headius merged commit a6c201f into jruby:jruby-10.0 Mar 23, 2026
84 checks passed
@jimtng jimtng deleted the java-prepend-bug branch March 24, 2026 09:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants