A mechanism that allows kotlinx.serialization plugin to preserve the
correct (program) order of properties after serializing/deserializing
descriptors to kotlin metadata, which is needed for correct and stable
json serialization of class hierarchies in incremental/multi-module scenario.
It uses protobuf extensions.
from runtime library.
If used unsubstituted, they cause
e: java.lang.IllegalArgumentException: Unbound type parameters are forbidden
because type parameter T from e.g. PolymorphicSerializer<T> leaked outside.
If return type of IrConstructor is different from containing class, we will
generate call to wrong <init> method, leading to VerifyError.
If we do not specify the type of irNull, it, by default, will be Nothing?,
when really we need Any?. This leads to CCE: cannot cast to Void at runtime.
Such situation may happen if generic class is customized by user
with object-kind serializer. In such case, both arguments from
generateSerializerGetter and generateSerializerFactory are objects.
See linked issue for details:
Fixes https://github.com/Kotlin/kotlinx.serialization/issues/749
This seems to be the only reasonable way to provide function declarations with
_correctly_ substituted type parameters without rewriting logic from scratch;
correctly scoped type parameters in IR are now required in serialization
plugin by all backends.
Also fix some missing upper bounds.
Originally reportFromPlugin method was introduced to address the problem
with loading of DefaultErrorMessages.Extension vis ServiceLoader.
For some cases this extension was not loaded by ServiceLoader because
classes was loaded via different class loader, common scenario here is
compiler plugins. Ideally we should load such extension point via
getService approach, but unfortunately to do that we need project and
DefaultErrorMessages.render is static method for now.
Also with reportFromPlugin approach is a problem -- all diagnostics
reported via this method has the same id: PLUGIN_[WARNING|ERROR|INFO]
and it isn't possible to suppress only one particular diagnostic.
To bypass this problem the new method
initializeFactoryNamesAndDefaultErrorMessages was introduced.
It basically store DiagnosticRenderer inside DiagnosticFactory.
It is not ideal, because one DiagnosticFactory could have different
renderers for different scenarios -- for compiler and for IDE, but
I think that it is better than reportByPlugin approach.
All mutable state for IR declarations should be either:
- var (mutable properties)
- or class member list
Mutable properties are straightforward to persist.
The class member list is handled in a special way.
kotlinx.serialization plugin now adds additional function to companions
of generic classes in order to overcome lack of reflection. This
helps retrieving generic serializers from KType.
The goal was to be able to use such symbols before BackendContext is even created – in psi2ir postprocessing step (i.e., IR compiler plugins).
Remove old code from serialization ir plugin.
LazyIR was emitted because plugin was not able to declare symbols, only to reference them.
Moreover, declarations added by frontend plugin were also unbound symbols produced by psi2ir,
and declaration stub generator was stubbing them with LazyIR – therefore access to global symbol table is not enough for plugins. IrProvider won't help here, because some functions produced by plugin have circular dependencies.
By moving compiler plugins step between psi2ir and declaration stub generator, both problems are resolved
– unbound symbols produced by psi2ir and compiler plugins are declared where they would be declared if this was a user code,
and only unbound symbols left are external dependencies, which is a correct input for lazy ir.