Skip to content

Do not generate certain interface mixin forwarders if not necessary #23674

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

jchyb
Copy link
Contributor

@jchyb jchyb commented Aug 6, 2025

Fixes #21177
This affects indirectly extended java interfaces, bringing the behavior closer to how scala 2 handles it. After this commit, the methods from those interfaces will not be generated, if they are unnecessary (e.g., where there is no conflict between parents when calling that method) even if -Xmixin-force-forwarders is set to true. Those previously added mixin forwarders caused meant that since specific parents were referenced in those methods, they had to be added to the interfaces array in the generated classfile (without being added to the signature, which caused an issue with getInterfaces and getGenericInterfaces not being equal).

Alternative solution would be to keep the mixing forwarder generation as it was, but change the signature generation in the GenBCode phase, but:
a) the current solution is how scala 2 does it
b) While I am not sure which solution is better in terms of binary compatibility, I feel like changing the signature would be worse

Also I copied one test from scala 2 codebase to make sure that we indeed generate the mixin forwarder if we actually need to

This affects indirectly extended java interfaces, bringing
the behavior closer to how scala 2 handles it. After this commit, the
methods from those interfaces will not be generated, if they are
unnecessary (e.g., where there is no conflict between parents when
calling that method) even if `-Xmixin-force-forwarders` is set to true.
Those previously added mixin forwarders caused meant that since specific
parents were referenced in those methods, they had to be added to the
`interfaces` array in the generated classfile (without being added to
the signature, which caused an issue with getInterfaces and
getGenericInterfaces not being equal).
!meth.isConstructor &&
meth.is(Method, butNot = PrivateOrAccessorOrDeferred) &&
(ctx.settings.mixinForwarderChoices.isTruthy || meth.owner.is(Scala2x) || needsDisambiguation || hasNonInterfaceDefinition ||
((ctx.settings.mixinForwarderChoices.isTruthy && !isJavaInterfaceIndirectlyExtended)|| meth.owner.is(Scala2x) || needsDisambiguation || hasNonInterfaceDefinition ||
generateJUnitForwarder || generateSerializationForwarder) &&
isInImplementingClass(meth)
Copy link
Contributor

@som-snytt som-snytt Aug 9, 2025

Choose a reason for hiding this comment

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

There is some formatting at https://github.com/scala/scala3/pull/23482/files which is about sealed.

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.

getGenericInterfaces and getInterfaces are not the same length after extending a generic Java class
2 participants