NB some cases such as captured extension receiver for an extension
lambda are not supported yet; to be discussed, to what extent should we
actually follow JVM code shape here.
1. Enum entry fields don't have nullability annotations.
2. Enum class special methods (values, valueOf) are not 'final'
(although they probably should be, javac generates corresponding
methods without ACC_FINAL flag).
3. Enum class special methods don't have nullability annotations.
4. Don't generate synthetic accessor for enum entry class constructor.
KT-37019 KT-37020 KT-37021
Synthetic marker parameters (of type
Lkotlin/jvm/internal/DefaultConstructorMarker;) don't have annotations
(including nullability annotations).
Also, for constructor accessors corresponding parameter should be
nullable (since we pass 'null' as an argument there).
KT-36966
In the newly added test, prior to this change, JVM IR was generating
DefaultImpls classes with calls to things like
`kotlin/collections/MutableList$DefaultImpls.spliterator` and other
default methods present in JDK 8+. This obviously didn't make much
sense. Although these weren't explicitly mentioned anywhere in the
bytecode, they caused some validation tools to report errors (e.g.
animalsniffer used in arrow).
Instead of generating these annotation classes as package-private on
JVM, serialize their metadata to the .kotlin_module file, and load it
when compiling dependent multiplatform modules.
The problem with generating them as package-private was that
kotlin-stdlib for JVM would end up declaring symbols from other
platforms, which would include some annotations from package
kotlin.native. But using that package is discouraged by some tools
because it has a Java keyword in its name. In particular, jlink refused
to work with such artifact altogether (KT-21266).
#KT-38652 Fixed
This fixes the weird cases when a class gets overwritten by an imperfect
copy, reduces the number of classes in the output if an inline function
contains an inline call that causes it to have regenerated anonymous
objects, and makes inlining of same module functions a bit faster in
general. On the other hand, this may increase memory footprint a bit
because classes cannot be flushed to the output jar, as the inliner
would not be able to locate classes for anonymous objects if they have
already been unloaded from memory.
The fields containing crossinline lambdas should be package-private to
avoid generating synthetic accessors, which break object regeneration.
Note that the inline methods cannot actually be called, as call sites
will attempt to read the captured lambda from a field through a *copy*
of the local containing the object, so these reads will not be inlined,
causing an exception at runtime:
inline fun f(crossinline g: () -> Unit) = object : I {
inline fun h() = g()
// effectively `val tmp = this; return tmp.$g()`:
override fun run() = h()
}
f {}.run() // NoSuchFieldError: $g
This particular example can be fixed by reusing locals for receiver
parameters in IrInlineCodegen, but explicitly assigning `this` to
another variable and calling an inline method on it will break it again.
(This is only applicable to the JVM_IR backend, as the non-IR one fails
to generate `f` at all for some other reason.)