[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
This commit is contained in:
committed by
Space Team
parent
2f99ac1cc0
commit
3713d95bb1
+12
@@ -48799,6 +48799,18 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
|
||||
runTest("compiler/testData/codegen/box/sealed/kt49752.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54028.kt")
|
||||
public void testKt54028() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54028_cursed.kt")
|
||||
public void testKt54028_cursed() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028_cursed.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("multipleFiles_enabled.kt")
|
||||
public void testMultipleFiles_enabled() throws Exception {
|
||||
|
||||
+12
@@ -48799,6 +48799,18 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
|
||||
runTest("compiler/testData/codegen/box/sealed/kt49752.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54028.kt")
|
||||
public void testKt54028() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54028_cursed.kt")
|
||||
public void testKt54028_cursed() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028_cursed.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("multipleFiles_enabled.kt")
|
||||
public void testMultipleFiles_enabled() throws Exception {
|
||||
|
||||
@@ -59,6 +59,14 @@ abstract class IrClass : IrDeclarationBase(), IrPossiblyExternalDeclaration,
|
||||
|
||||
abstract var valueClassRepresentation: ValueClassRepresentation<IrSimpleType>?
|
||||
|
||||
/**
|
||||
* If this is a sealed class or interface, this list contains symbols of all its immediate
|
||||
* subclasses.
|
||||
* Otherwise, this is an empty list.
|
||||
*
|
||||
* NOTE: If this [IrClass] was deserialized from a klib, this list will always be empty!
|
||||
* See [KT-54028](https://youtrack.jetbrains.com/issue/KT-54028).
|
||||
*/
|
||||
abstract var sealedSubclasses: List<IrClassSymbol>
|
||||
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
||||
|
||||
@@ -199,7 +199,15 @@ object IrTree : AbstractTreeBuilder() {
|
||||
type<ValueClassRepresentation<*>>().withArgs(type(Packages.types, "IrSimpleType")),
|
||||
nullable = true,
|
||||
)
|
||||
+listField("sealedSubclasses", classSymbolType, mutability = Var)
|
||||
+listField("sealedSubclasses", classSymbolType, mutability = Var) {
|
||||
kdoc = """
|
||||
If this is a sealed class or interface, this list contains symbols of all its immediate subclasses.
|
||||
Otherwise, this is an empty list.
|
||||
|
||||
NOTE: If this [${elementName2typeName(this@element.name)}] was deserialized from a klib, this list will always be empty!
|
||||
See [KT-54028](https://youtrack.jetbrains.com/issue/KT-54028).
|
||||
""".trimIndent()
|
||||
}
|
||||
}
|
||||
val attributeContainer: ElementConfig by element(Declaration) {
|
||||
kDoc = """
|
||||
|
||||
+2
-1
@@ -389,7 +389,8 @@ class IrDeclarationDeserializer(
|
||||
else -> computeMissingInlineClassRepresentationForCompatibility(this)
|
||||
}
|
||||
|
||||
sealedSubclasses = proto.sealedSubclassList.map { deserializeIrSymbol(it).checkSymbolType(CLASS_SYMBOL) }
|
||||
// It has been desided not to deserialize the list of sealed subclasses because of KT-54028
|
||||
// sealedSubclasses = proto.sealedSubclassList.map { deserializeIrSymbol(it).checkSymbolType(CLASS_SYMBOL) }
|
||||
|
||||
fakeOverrideBuilder.enqueueClass(this, signature, compatibilityMode)
|
||||
}
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
// KT-54028
|
||||
|
||||
// MODULE: lib
|
||||
// FILE: file1.kt
|
||||
|
||||
sealed interface LazyGridLayoutInfo {
|
||||
fun ok(): String
|
||||
}
|
||||
|
||||
// FILE: file2.kt
|
||||
|
||||
class LazyGridState {
|
||||
val layoutInfo: LazyGridLayoutInfo
|
||||
get() = EmptyLazyGridLayoutInfo
|
||||
}
|
||||
|
||||
private object EmptyLazyGridLayoutInfo : LazyGridLayoutInfo {
|
||||
override fun ok() = "OK"
|
||||
}
|
||||
|
||||
// MODULE: main(lib)
|
||||
// FILE: main.kt
|
||||
|
||||
fun box(): String {
|
||||
return LazyGridState().layoutInfo.ok()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
// ALLOW_FILES_WITH_SAME_NAMES
|
||||
|
||||
// The test infrastructure for Kotlin/Native doesn't allow files with same names.
|
||||
// IGNORE_BACKEND: NATIVE
|
||||
|
||||
// IGNORE_BACKEND: JS
|
||||
// IGNORE_BACKEND: WASM
|
||||
// IGNORE_BACKEND_K2: JS_IR
|
||||
|
||||
// Test that if we have two different files with the same name in the same package, KT-54028 doesn't reproduce.
|
||||
|
||||
// MODULE: lib
|
||||
|
||||
// FILE: cursed.kt
|
||||
|
||||
sealed interface LazyGridLayoutInfo {
|
||||
fun ok(): String
|
||||
}
|
||||
|
||||
// FILE: cursed.kt
|
||||
|
||||
class LazyGridState {
|
||||
val layoutInfo: LazyGridLayoutInfo
|
||||
get() = EmptyLazyGridLayoutInfo
|
||||
}
|
||||
|
||||
private object EmptyLazyGridLayoutInfo : LazyGridLayoutInfo {
|
||||
override fun ok() = "OK"
|
||||
}
|
||||
|
||||
// MODULE: main(lib)
|
||||
// FILE: main.kt
|
||||
|
||||
fun box(): String {
|
||||
return LazyGridState().layoutInfo.ok()
|
||||
}
|
||||
|
||||
+2
-1
@@ -1,6 +1,7 @@
|
||||
// FIR_IDENTICAL
|
||||
// SKIP_KLIB_TEST
|
||||
sealed class Expr {
|
||||
class Const(val number: Double) : Expr()
|
||||
class Sum(val e1: Expr, val e2: Expr) : Expr()
|
||||
object NotANumber : Expr()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// IGNORE_BACKEND_K2: JS_IR
|
||||
// IGNORE_BACKEND_K2: JS_IR_ES6
|
||||
// !LANGUAGE: +MultiPlatformProjects
|
||||
// SKIP_KLIB_TEST
|
||||
|
||||
expect sealed class Ops()
|
||||
expect class Add() : Ops
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// WITH_STDLIB
|
||||
// SKIP_KLIB_TEST
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// IGNORE_BACKEND: JS_IR_ES6
|
||||
|
||||
|
||||
+12
@@ -46309,6 +46309,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt49752.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54028.kt")
|
||||
public void testKt54028() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54028_cursed.kt")
|
||||
public void testKt54028_cursed() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028_cursed.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("multipleFiles_enabled.kt")
|
||||
public void testMultipleFiles_enabled() throws Exception {
|
||||
|
||||
+12
@@ -48799,6 +48799,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/sealed/kt49752.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54028.kt")
|
||||
public void testKt54028() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54028_cursed.kt")
|
||||
public void testKt54028_cursed() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028_cursed.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("multipleFiles_enabled.kt")
|
||||
public void testMultipleFiles_enabled() throws Exception {
|
||||
|
||||
+12
@@ -48799,6 +48799,18 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack
|
||||
runTest("compiler/testData/codegen/box/sealed/kt49752.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54028.kt")
|
||||
public void testKt54028() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54028_cursed.kt")
|
||||
public void testKt54028_cursed() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028_cursed.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("multipleFiles_enabled.kt")
|
||||
public void testMultipleFiles_enabled() throws Exception {
|
||||
|
||||
+10
@@ -37475,6 +37475,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/sealed/kt49752.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt54028.kt")
|
||||
public void testKt54028() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt54028_cursed.kt")
|
||||
public void testKt54028_cursed() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028_cursed.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("multipleFiles_enabled.kt")
|
||||
public void testMultipleFiles_enabled() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/multipleFiles_enabled.kt");
|
||||
|
||||
+12
@@ -34365,6 +34365,18 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt49752.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54028.kt")
|
||||
public void testKt54028() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54028_cursed.kt")
|
||||
public void testKt54028_cursed() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028_cursed.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("multipleFiles_enabled.kt")
|
||||
public void testMultipleFiles_enabled() throws Exception {
|
||||
|
||||
+12
@@ -34677,6 +34677,18 @@ public class FirJsCodegenBoxTestGenerated extends AbstractFirJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt49752.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54028.kt")
|
||||
public void testKt54028() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54028_cursed.kt")
|
||||
public void testKt54028_cursed() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028_cursed.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("multipleFiles_enabled.kt")
|
||||
public void testMultipleFiles_enabled() throws Exception {
|
||||
|
||||
+12
@@ -34677,6 +34677,18 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt49752.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54028.kt")
|
||||
public void testKt54028() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54028_cursed.kt")
|
||||
public void testKt54028_cursed() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028_cursed.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("multipleFiles_enabled.kt")
|
||||
public void testMultipleFiles_enabled() throws Exception {
|
||||
|
||||
+12
@@ -34677,6 +34677,18 @@ public class IrJsES6CodegenBoxTestGenerated extends AbstractIrJsES6CodegenBoxTes
|
||||
runTest("compiler/testData/codegen/box/sealed/kt49752.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54028.kt")
|
||||
public void testKt54028() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54028_cursed.kt")
|
||||
public void testKt54028_cursed() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028_cursed.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("multipleFiles_enabled.kt")
|
||||
public void testMultipleFiles_enabled() throws Exception {
|
||||
|
||||
+12
@@ -38735,6 +38735,18 @@ public class FirNativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTe
|
||||
runTest("compiler/testData/codegen/box/sealed/kt49752.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54028.kt")
|
||||
public void testKt54028() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54028_cursed.kt")
|
||||
public void testKt54028_cursed() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028_cursed.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("multipleFiles_enabled.kt")
|
||||
public void testMultipleFiles_enabled() throws Exception {
|
||||
|
||||
+12
@@ -39693,6 +39693,18 @@ public class FirNativeCodegenBoxTestNoPLGenerated extends AbstractNativeCodegenB
|
||||
runTest("compiler/testData/codegen/box/sealed/kt49752.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54028.kt")
|
||||
public void testKt54028() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54028_cursed.kt")
|
||||
public void testKt54028_cursed() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028_cursed.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("multipleFiles_enabled.kt")
|
||||
public void testMultipleFiles_enabled() throws Exception {
|
||||
|
||||
+12
@@ -38256,6 +38256,18 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
|
||||
runTest("compiler/testData/codegen/box/sealed/kt49752.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54028.kt")
|
||||
public void testKt54028() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54028_cursed.kt")
|
||||
public void testKt54028_cursed() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028_cursed.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("multipleFiles_enabled.kt")
|
||||
public void testMultipleFiles_enabled() throws Exception {
|
||||
|
||||
+12
@@ -39214,6 +39214,18 @@ public class NativeCodegenBoxTestNoPLGenerated extends AbstractNativeCodegenBoxT
|
||||
runTest("compiler/testData/codegen/box/sealed/kt49752.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54028.kt")
|
||||
public void testKt54028() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54028_cursed.kt")
|
||||
public void testKt54028_cursed() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028_cursed.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("multipleFiles_enabled.kt")
|
||||
public void testMultipleFiles_enabled() throws Exception {
|
||||
|
||||
Generated
+10
@@ -30990,6 +30990,16 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
|
||||
runTest("compiler/testData/codegen/box/sealed/kt49752.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt54028.kt")
|
||||
public void testKt54028() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt54028_cursed.kt")
|
||||
public void testKt54028_cursed() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/kt54028_cursed.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("multipleFiles_enabled.kt")
|
||||
public void testMultipleFiles_enabled() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sealed/multipleFiles_enabled.kt");
|
||||
|
||||
Reference in New Issue
Block a user