Files
kotlin-fork/native/native.tests
Sergej Jaskiewicz 3713d95bb1 [klib] Don't deserialize the list of sealed subclasses from klibs
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
2023-04-05 15:51:54 +00:00
..

Running tests

  • To run all tests, use ./gradlew :native:native.tests:test. Please note, this Gradle task is available only in development environment and it not available at CI server.
  • To execute certain tests only, use the appropriate Gradle tasks. Example: ./gradlew :native:native.tests:codegenBoxTest
  • To execute InteropIndexer tests for all targets, use:
for TARGET in android_x64 android_x86 android_arm32 android_arm64 \
              ios_arm32 ios_arm64 ios_x64 ios_simulator_arm64 \
              linux_x64 linux_arm64 linux_arm32_hfp linux_mips32 linux_mipsel32 \
              macos_x64 macos_arm64 \
              mingw_x86 mingw_x64 \
              tvos_arm64 tvos_x64 tvos_simulator_arm64 \
              wasm32 \
              watchos_arm32 watchos_arm64 watchos_x86 watchos_x64 watchos_simulator_arm64 watchos_device_arm64
do
  echo $TARGET             
  ./gradlew :native:native.tests:interopIndexerTest -Pkotlin.internal.native.test.target=$TARGET
done
  • To re-generate tests, use ./gradlew :native:native.tests:generateTests

For more details see Testing.