Skip to content

KT-89073 [SLC] Preserve @JvmExposeBoxed when no boxed wrapper is generated - #7948

Open
Alexey Belkov (abelkov) wants to merge 9 commits into
masterfrom
belkov/KT-89073-expose-boxed-overloads
Open

KT-89073 [SLC] Preserve @JvmExposeBoxed when no boxed wrapper is generated#7948
Alexey Belkov (abelkov) wants to merge 9 commits into
masterfrom
belkov/KT-89073-expose-boxed-overloads

Conversation

@abelkov

Copy link
Copy Markdown
Contributor

No description provided.

The JVM backend suite covers several declaration shapes that were absent
from symbol light classes.

Add explicit and directive cases for large-arity methods and FunctionN,
nullable Result bounds, secondary, internal, and default constructors,
nullable data-class fields, companion extensions, IntroducedAt
constructors, and version overloads.

Note: some of this testdata exposes existing bugs:
KT-86855, KT-89069, KT-89073.
Note: the main problem described in KT-89073 is reproduced by the
existing test `jvmOverloadsValueParameter.java`.

^KT-89073
The JVM backend does not generate a boxed wrapper when an explicitly
annotated declaration has no value-class type that needs boxing. Instead, it
keeps a single declaration with `@JvmExposeBoxed`. For functions and
property accessors, `@JvmName` takes precedence over
`@JvmExposeBoxed.jvmName` when both annotations provide a name.

This case also arises with `@JvmOverloads`: annotations are copied to
generated overloads before value-class lowering, and removing a defaulted
value-class parameter can leave an overload with nothing to box.

Symbol light classes modeled these declarations as regular methods. They
therefore filtered out `@JvmExposeBoxed` and could report a Java name that
was absent from bytecode.

Introduce `REGULAR`, `BOXED`, and `EXPOSED_AS_IS` light-method kinds.
`EXPOSED_AS_IS` uses regular JVM type mapping while retaining both
annotations and their naming precedence. Use it for explicitly annotated
declarations for which the backend emits no separate boxed wrapper.

Apply the same handling to functions, property accessors, and constructors,
and update source light-class expectations to match compiled declarations.

^KT-89073 Fixed
When the JVM backend creates a boxed method, it removes `@JvmName`.
If `@JvmExposeBoxed` has no explicit name, the backend copies the
`@JvmName` value to its `jvmName` argument. The same applies when
`@JvmExposeBoxed` is synthesized for a containing class annotation or
the compiler option.

Symbol light classes already used the correct name for the boxed method,
but rendered `@JvmExposeBoxed` without the copied argument. Its
annotation therefore differed from the corresponding bytecode
declaration.

Inspect both annotations before `@JvmName` is filtered from the boxed
method. Keep an explicit `@JvmExposeBoxed` name unchanged. Otherwise,
use the `@JvmName` argument when creating a synthetic annotation or
replacing a bare source annotation. Preserve the Kotlin origin when
replacing an annotation.

^KT-89073
@kotlin-safemerge

kotlin-safemerge Bot commented Sep 4, 2026

Copy link
Copy Markdown

Code Owners

RuleOwnersApproval
/​analysis/​
kotlin-analysis-api

dimonchik0036
*Generated.​java
dimonchik0036
PR commands for maintainers
CommandDescriptionParameters
/safe-mergeRebase-merges with automatic fixup commit squashing--fixup Autosquash fixup commits (on by default)
/safe-squash-mergeSquash-merges with optional commit title/body override--title Title of the squashed commit
--message Body of the squashed commit
/dry-runRuns the test pipeline with changes rebased on latest master--retry Retry the CI run on failure
/test-publicTriggers the public test suite without rebasing on latest master
/test-privateTriggers the private test suite without rebasing on latest master
/codeownersTriggers code owners check and comment update
/fixupSquashes fixup commits and force pushes the branch
/cancel-coordinatorCancels the merge coordinator currently running for this branch
/cherry-pickCherry-picks this pull request onto a target release branch--target Release version to cherry-pick onto

arguments = listOfNotNull(exposedName),
)
} else if (exposedName != null) {
currentRawAnnotations[exposeBoxedAnnotationIndex] = SymbolLightSimpleAnnotation(

@dimonchik0036 Dmitrii Gridin (dimonchik0036) Sep 4, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What's a practical benefit of copying the argument?
The presence of the annotation is a useful sign to understand whether the declaration was generated, but which problem does the argument solve?
The method already has a proper boxed name. The backend can optimize the metadata in the same way by stripping this redundant data

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.

2 participants