According to
`FirNativeCodegenBoxTestGenerated.testNestedClassesInAnnotations`,
the annotation
`kotlin.internal.PlatformDependent` is
unresolved reference.
^KT-58549 Fixed
Normally during metadata compilation we use
`K2MetadataCompiler` and it serializes
metadata to klibs without generating IR.
Native shared compilation uses the K2Native
compiler, which generates klibs based on both
the fir and fir2ir information.
It would be nice to reuse `K2MetadataCompiler`
for native shared, but currently it has no
support for the commonizer, and also reads
the stdlib metadata from a jar instead of a
klib, and there's no simple idiomatic way
to pass the `distribution.klib` value down
to `KLibResolverHelper` (native compilation
has some commonized dependencies, and they
explicitly depend on `stdlib`, so we must
resolve it this way or strip it away to be
able to use the metadata jar instead). There
may be other issues, I only digged a bit.
Instead, this change modifies the K2Native
in such a way that it can generate klibs
with metadata without fir2ir info.
Note that this change does not fix KT-58139,
because KT-58139 fails due to performing the
constants evaluation directly during the
metadata serialization when the needed info
does (and, as I was told, should) not exist
(namely, valid property initializers).
^KT-58444 Fixed
- Mangled names of property accessors now include context receiver
types of the corresponding property when computed from FIR.
- Context receivers are now supported when computing mangled names
from IR
- IrBasedDescriptors now account for context receivers
^KT-57435 Fixed
Single-letter names were very confusing, especially in declarations like
```kotlin
private inline fun <
reified D : IrDeclaration,
reified ES : IrDelegatingSymbol<AS, D, *>,
reified AS : IrBindableSymbol<*, D>
> finalizeExpectActual(
expectSymbol: ES,
actualSymbol: IrSymbol,
noinline actualizer: (e: D, a: D) -> Unit
)
```
Both explicitly specified and default argument expressions are considered.
In case an argument expression is considered as 'unlinked' the whole annotation
is removed from the declaration. An appropriate compiler warning logged for each
such case.
tl;dr the current design of klibs does not allow to properly deserialize
the list of sealed subclasses in a sound way. It is possible that
a subclass of a sealed class is declared in a different file, AND is
private in that file.
A more detailed explanation:
Right now we don't serialize file signatures at all.
However, a private declaration's signature must necessarily include
the file signature.
How do we serialize a private declaration's signature into a klib
and deserialize it later?
**Serialization** is simple: we just serialize the file signature as
an empty protobuf message.
When we are **deserializing** a private declaration, we look at the file
that is being deserialized right now, and construct the file signature
based on that.
This logic, however, doesn't always work. An example is KT-54028.
Basically, if we have a sealed interface with a private implementor
declared in a different file, this breaks:
1. We are deserializing the sealed interface. The deserializer knows
that we are now in the file in which the sealed interface is declared.
2. As part of deserializing the interface, we deserialize its sealed
subclasses.
3. Naturally, we come to deserializing the private implementor that is
declared in another file, but the deserializer still thinks that we are
in the file in which the interface is declared. A wrong signature is
created, which leads to linkage failure.
We *could* fix this by properly serializing the file signature,
i.e. instead of an empty protobuf message we could write the file path
and its package to the klib. However, there a problems with this
approach:
- The current design of signatures allows a situation where two
different files can have the same relative path
(for example, with the help of the `-Xklib-relative-path-base` compiler
flag) *and* the same package, which would introduce ambiguity during
linkage.
- Most importantly, this appoach won't work well with incremental
compilation of klibs. Currently we rely on the assumption that all
cross-file references are handled with public signatures, and private
signatures are only used inside a single file. This allows to move
declarations across files without recompiling it's use sites.
It has been decided to apply the following hacky solution: we just don't
deserialize the list of sealed subclasses from klibs.
The list of sealed subclasses is not used in lowerings, so it should be
safe.
#KT-54028 Fixed
Kotlin/Native codegen needs to deserialize all fields throughout the class hierarchy to build the proper binary class layout. That becomes impossible with the guard condition that prevents loading private top-level classes from another module in LazyIR (see https://github.com/JetBrains/kotlin/blob/2a4d8800374578c1aa9ec9c996b393a98f5a6e3b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt#L701). The guard suits well for the partial linkage needs, but it causes the codegen to fail with `Unbound public symbol IrClassPublicSymbolImpl: [ File '/file/in/the/library.kt' <- private.top.level/ClassDeclaration|null[0] ]` error.
To prevent this the guard is removed. This does not influence the partial linkage in general except for the different error message being generated: `Function 'foo' can not be called: Private function declared in module <A> can not be accessed in module <B>` instead of `Function 'foo' can not be called: No function found for symbol '<symbol>'`.
#KT-54469
1. Leaving no unbound symbols in the IR tree, KT-54491:
- All unbound symbols are bound to synthetic stub declarations
- Improved detection of the root cause for every partially linked classifier
- Improved error messages
2. Visibility valiation, KT-54469
3. Always check deserialized symbols:
If the deserialized symbol mismatches the symbol kind at the call site in the deserializer then generate and reference another symbol with the same signature. In case PL is off, just throw IrSymbolTypeMismatchException.
4. Handle class inheritance violation:
- Detect illegal inheritance (ex: inheriting from a final class)
- Detect invalid constructor delegation (ex: delegating to another class than the direct superclass)
- Simplification: Reduce the number of PartialLinkageCase subclasses
- Reworked error message generation to have shorter and clearer messages
5. Handle class transformations and all known side-effects, examples:
- nested <-> inner
- class <-> enum/object
- adding/removing subclasses of sealed class
- adding/removing enum entries
6. Check direct instantiation of abstract class.
Such instantiation could be possible if a class was non-abstract in the previous version of a library.
7. Handle unlinked annotations on declarations.
Such annotations are removed from the IR. The appropriate compiler error message is produced for every individual case.
8. Handle value argument count mismatch at call sites
9. Handle calling suspend function from non-suspend context.
This could happen if a suspen function was non-suspend in the previous version of a library.
10. Handle overriding inline callables.
Only the leaf final callable can be marked with `inline`.
11. Detect illegal non-local returns from noinline/crossinline lambdas.
With the partial linkage turned on it's hard to predict whether a newly created IrSymbol that is added to the SymbolTable via one of referenceXXX() calls will or won't be bound to some declaration. The latter may happen in certain cases, for example when the symbol refers from an IR expression to a non-top level declaration that was removed in newer version of Kotlin library (KLIB). Unless such symbol is registered as "probably unbound" it remains invisible for the linkage process.
The optimization that allows to reference symbols without registering them as "probably unbound" is fragile. It's better to avoid calling any referenceXXX(reg = false) functions. Instead, wherever it is s suitable it is recommended to use one of the appropriate declareXXX() calls.
For the future: Consider implementing the optimization once again for the new "flat" ID signatures.
Also: Temporarily mute assertion that checks symbols overwrites in SymbolTable ^KT-57049
In the lowered IR there are often references to type parameters whose
containers are not in the current scope. This is incorrect semantically,
but it works in practice due to erasure, so when the mangler is used on
the lowered IR, we don't want to crash the compiler.