From 81d9cf76f2f21803cfdab4f62b19eb3794dab990 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Mon, 6 Apr 2020 18:16:23 +0300 Subject: [PATCH] FIR: Add java.io.Serializable as supertypes to built-in classes --- .../testData/builtIns/kotlin.txt | 42 +++++++++--------- .../testData/resolve/whenElse.txt | 2 +- .../j+k/serializableString.kt | 6 +++ .../j+k/serializableString.txt | 6 +++ .../resolveWithStdlib/withInInitializer.txt | 4 +- ...FirDiagnosticsWithStdlibTestGenerated.java | 5 +++ .../deserialization/ClassDeserialization.kt | 23 +++++++++- .../genericValMultipleUpperBounds.kt | 1 - .../diagnostics/tests/Serializable.fir.kt | 44 +++++++++---------- .../diagnostics/tests/j+k/serializable.fir.kt | 44 +++++++++---------- 10 files changed, 106 insertions(+), 71 deletions(-) create mode 100644 compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/serializableString.kt create mode 100644 compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/serializableString.txt diff --git a/compiler/fir/analysis-tests/testData/builtIns/kotlin.txt b/compiler/fir/analysis-tests/testData/builtIns/kotlin.txt index 7e9f8bb96ef..4b6c794d08f 100644 --- a/compiler/fir/analysis-tests/testData/builtIns/kotlin.txt +++ b/compiler/fir/analysis-tests/testData/builtIns/kotlin.txt @@ -42,7 +42,7 @@ public open class Any { } -public final class Array : R|kotlin/Any|, R|kotlin/Cloneable| { +public final class Array : R|kotlin/Any|, R|kotlin/Cloneable|, R|java/io/Serializable| { public final operator fun get(index: R|kotlin/Int|): R|T| public final operator fun iterator(): R|kotlin/collections/Iterator| @@ -58,7 +58,7 @@ public final class Array : R|kotlin/Any|, R|kotlin/Cloneable| { } -public final class Boolean : R|kotlin/Comparable| { +public final class Boolean : R|kotlin/Comparable|, R|java/io/Serializable| { public final infix fun and(other: R|kotlin/Boolean|): R|kotlin/Boolean| public open operator fun compareTo(other: R|kotlin/Boolean|): R|kotlin/Int| @@ -78,7 +78,7 @@ public final class Boolean : R|kotlin/Comparable| { } -public final class BooleanArray : R|kotlin/Any|, R|kotlin/Cloneable| { +public final class BooleanArray : R|kotlin/Any|, R|kotlin/Cloneable|, R|java/io/Serializable| { public final operator fun get(index: R|kotlin/Int|): R|kotlin/Boolean| public final operator fun iterator(): R|kotlin/collections/BooleanIterator| @@ -96,7 +96,7 @@ public final class BooleanArray : R|kotlin/Any|, R|kotlin/Cloneable| { } -public final class Byte : R|kotlin/Number|, R|kotlin/Comparable| { +public final class Byte : R|kotlin/Number|, R|kotlin/Comparable|, R|java/io/Serializable| { public open operator fun compareTo(other: R|kotlin/Byte|): R|kotlin/Int| public final operator fun compareTo(other: R|kotlin/Double|): R|kotlin/Int| @@ -220,7 +220,7 @@ public final class Byte : R|kotlin/Number|, R|kotlin/Comparable| { } -public final class ByteArray : R|kotlin/Any|, R|kotlin/Cloneable| { +public final class ByteArray : R|kotlin/Any|, R|kotlin/Cloneable|, R|java/io/Serializable| { public final operator fun get(index: R|kotlin/Int|): R|kotlin/Byte| public final operator fun iterator(): R|kotlin/collections/ByteIterator| @@ -238,7 +238,7 @@ public final class ByteArray : R|kotlin/Any|, R|kotlin/Cloneable| { } -public final class Char : R|kotlin/Comparable| { +public final class Char : R|kotlin/Comparable|, R|java/io/Serializable| { public open operator fun compareTo(other: R|kotlin/Char|): R|kotlin/Int| public final operator fun dec(): R|kotlin/Char| @@ -306,7 +306,7 @@ public final class Char : R|kotlin/Comparable| { } -public final class CharArray : R|kotlin/Any|, R|kotlin/Cloneable| { +public final class CharArray : R|kotlin/Any|, R|kotlin/Cloneable|, R|java/io/Serializable| { public final operator fun get(index: R|kotlin/Int|): R|kotlin/Char| public final operator fun iterator(): R|kotlin/collections/CharIterator| @@ -372,7 +372,7 @@ public final enum class DeprecationLevel : R|kotlin/Enum| { +public final class Double : R|kotlin/Number|, R|kotlin/Comparable|, R|java/io/Serializable| { public final operator fun compareTo(other: R|kotlin/Byte|): R|kotlin/Int| public open operator fun compareTo(other: R|kotlin/Double|): R|kotlin/Int| @@ -497,7 +497,7 @@ public final class Double : R|kotlin/Number|, R|kotlin/Comparable } -public final class DoubleArray : R|kotlin/Any|, R|kotlin/Cloneable| { +public final class DoubleArray : R|kotlin/Any|, R|kotlin/Cloneable|, R|java/io/Serializable| { public final operator fun get(index: R|kotlin/Int|): R|kotlin/Double| public final operator fun iterator(): R|kotlin/collections/DoubleIterator| @@ -520,7 +520,7 @@ public final class DoubleArray : R|kotlin/Any|, R|kotlin/Cloneable| { } -public abstract class Enum : R|kotlin/Comparable| { +public abstract class Enum : R|kotlin/Comparable|, R|java/io/Serializable| { protected final fun clone(): R|kotlin/Any| public final operator fun compareTo(other: R|E|): R|kotlin/Int| @@ -551,7 +551,7 @@ public abstract class Enum : R|kotlin/Comparable| { } -public final class Float : R|kotlin/Number|, R|kotlin/Comparable| { +public final class Float : R|kotlin/Number|, R|kotlin/Comparable|, R|java/io/Serializable| { public final operator fun compareTo(other: R|kotlin/Byte|): R|kotlin/Int| public final operator fun compareTo(other: R|kotlin/Double|): R|kotlin/Int| @@ -676,7 +676,7 @@ public final class Float : R|kotlin/Number|, R|kotlin/Comparable| } -public final class FloatArray : R|kotlin/Any|, R|kotlin/Cloneable| { +public final class FloatArray : R|kotlin/Any|, R|kotlin/Cloneable|, R|java/io/Serializable| { public final operator fun get(index: R|kotlin/Int|): R|kotlin/Float| public final operator fun iterator(): R|kotlin/collections/FloatIterator| @@ -697,7 +697,7 @@ public final class FloatArray : R|kotlin/Any|, R|kotlin/Cloneable| { public abstract interface Function : R|kotlin/Any| { } -public final class Int : R|kotlin/Number|, R|kotlin/Comparable| { +public final class Int : R|kotlin/Number|, R|kotlin/Comparable|, R|java/io/Serializable| { public final infix fun and(other: R|kotlin/Int|): R|kotlin/Int| public final operator fun compareTo(other: R|kotlin/Byte|): R|kotlin/Int| @@ -835,7 +835,7 @@ public final class Int : R|kotlin/Number|, R|kotlin/Comparable| { } -public final class IntArray : R|kotlin/Any|, R|kotlin/Cloneable| { +public final class IntArray : R|kotlin/Any|, R|kotlin/Cloneable|, R|java/io/Serializable| { public final operator fun get(index: R|kotlin/Int|): R|kotlin/Int| public final operator fun iterator(): R|kotlin/collections/IntIterator| @@ -853,7 +853,7 @@ public final class IntArray : R|kotlin/Any|, R|kotlin/Cloneable| { } -public final class Long : R|kotlin/Number|, R|kotlin/Comparable| { +public final class Long : R|kotlin/Number|, R|kotlin/Comparable|, R|java/io/Serializable| { public final infix fun and(other: R|kotlin/Long|): R|kotlin/Long| public final operator fun compareTo(other: R|kotlin/Byte|): R|kotlin/Int| @@ -991,7 +991,7 @@ public final class Long : R|kotlin/Number|, R|kotlin/Comparable| { } -public final class LongArray : R|kotlin/Any|, R|kotlin/Cloneable| { +public final class LongArray : R|kotlin/Any|, R|kotlin/Cloneable|, R|java/io/Serializable| { public final operator fun get(index: R|kotlin/Int|): R|kotlin/Long| public final operator fun iterator(): R|kotlin/collections/LongIterator| @@ -1014,7 +1014,7 @@ public final class Nothing { } -public abstract class Number : R|kotlin/Any| { +public abstract class Number : R|kotlin/Any|, R|java/io/Serializable| { public abstract fun toByte(): R|kotlin/Byte| public abstract fun toChar(): R|kotlin/Char| @@ -1057,7 +1057,7 @@ public abstract class Number : R|kotlin/Any| { } -public final class Short : R|kotlin/Number|, R|kotlin/Comparable| { +public final class Short : R|kotlin/Number|, R|kotlin/Comparable|, R|java/io/Serializable| { public final operator fun compareTo(other: R|kotlin/Byte|): R|kotlin/Int| public final operator fun compareTo(other: R|kotlin/Double|): R|kotlin/Int| @@ -1181,7 +1181,7 @@ public final class Short : R|kotlin/Number|, R|kotlin/Comparable| } -public final class ShortArray : R|kotlin/Any|, R|kotlin/Cloneable| { +public final class ShortArray : R|kotlin/Any|, R|kotlin/Cloneable|, R|java/io/Serializable| { public final operator fun get(index: R|kotlin/Int|): R|kotlin/Short| public final operator fun iterator(): R|kotlin/collections/ShortIterator| @@ -1207,7 +1207,7 @@ public final class ShortArray : R|kotlin/Any|, R|kotlin/Cloneable| { } -public final class String : R|kotlin/Comparable|, R|kotlin/CharSequence| { +public final class String : R|kotlin/Comparable|, R|kotlin/CharSequence|, R|java/io/Serializable| { public open operator fun compareTo(other: R|kotlin/String|): R|kotlin/Int| public open operator fun get(index: R|kotlin/Int|): R|kotlin/Char| @@ -1236,7 +1236,7 @@ public final class String : R|kotlin/Comparable|, R|kotlin/CharSe } -public open class Throwable : R|kotlin/Any| { +public open class Throwable : R|kotlin/Any|, R|java/io/Serializable| { public open val cause: R|kotlin/Throwable?| public get(): R|kotlin/Throwable?| diff --git a/compiler/fir/analysis-tests/testData/resolve/whenElse.txt b/compiler/fir/analysis-tests/testData/resolve/whenElse.txt index f24bbf8f7f6..f9154d38bee 100644 --- a/compiler/fir/analysis-tests/testData/resolve/whenElse.txt +++ b/compiler/fir/analysis-tests/testData/resolve/whenElse.txt @@ -28,7 +28,7 @@ FILE: whenElse.kt public get(): R|B| } - public final fun get(f: R|kotlin/Boolean|): R|kotlin/Comparable| { + public final fun get(f: R|kotlin/Boolean|): R|it(kotlin/Comparable & java/io/Serializable)| { ^get when () { R|/f| -> { Q|A|.R|/A.A1| diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/serializableString.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/serializableString.kt new file mode 100644 index 00000000000..6127a2f22ad --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/serializableString.kt @@ -0,0 +1,6 @@ +// FULL_JDK +fun foo(x: java.io.Serializable) {} + +fun main() { + foo("") +} diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/serializableString.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/serializableString.txt new file mode 100644 index 00000000000..3963c2d3399 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/serializableString.txt @@ -0,0 +1,6 @@ +FILE: serializableString.kt + public final fun foo(x: R|java/io/Serializable|): R|kotlin/Unit| { + } + public final fun main(): R|kotlin/Unit| { + R|/foo|(String()) + } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/withInInitializer.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/withInInitializer.txt index 5e84b38e1f6..119e30466b6 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/withInInitializer.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/withInInitializer.txt @@ -13,8 +13,8 @@ FILE: withInInitializer.kt super() } - public final val list: R|kotlin/collections/List>| = R|kotlin/collections/listOf||>(vararg(Int(1), Int(2), Int(3), String())) - public get(): R|kotlin/collections/List>| + public final val list: R|kotlin/collections/List & java/io/Serializable)>| = R|kotlin/collections/listOf| & java/io/Serializable)|>(vararg(Int(1), Int(2), Int(3), String())) + public get(): R|kotlin/collections/List & java/io/Serializable)>| public final val data: R|First| = R|/First.First|(Int(42)) public get(): R|First| diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithStdlibTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithStdlibTestGenerated.java index 186c2897041..6a7cff8a59d 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithStdlibTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithStdlibTestGenerated.java @@ -690,6 +690,11 @@ public class FirDiagnosticsWithStdlibTestGenerated extends AbstractFirDiagnostic runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/RawType.kt"); } + @TestMetadata("serializableString.kt") + public void testSerializableString() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/serializableString.kt"); + } + @TestMetadata("smartSet.kt") public void testSmartSet() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/smartSet.kt"); diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt index 2c7e4de4b97..67f90f653b7 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.fir.deserialization import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.builtins.jvm.JvmBuiltInsSettings import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities @@ -17,12 +18,15 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.generateValueOfFunction import org.jetbrains.kotlin.fir.generateValuesFunction -import org.jetbrains.kotlin.fir.resolve.impl.FirClonableSymbolProvider.Companion.CLONE import org.jetbrains.kotlin.fir.resolve.impl.FirClonableSymbolProvider.Companion.CLONABLE_CLASS_ID +import org.jetbrains.kotlin.fir.resolve.impl.FirClonableSymbolProvider.Companion.CLONE import org.jetbrains.kotlin.fir.scopes.KotlinScopeProvider import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag -import org.jetbrains.kotlin.fir.symbols.impl.* +import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl +import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl @@ -32,6 +36,7 @@ import org.jetbrains.kotlin.metadata.deserialization.NameResolver import org.jetbrains.kotlin.metadata.deserialization.TypeTable import org.jetbrains.kotlin.metadata.deserialization.supertypes import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.serialization.deserialization.ProtoEnumFlags import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource @@ -147,6 +152,7 @@ fun deserializeClassToSymbol( } } addCloneForArrayIfNeeded(classId) + addSerializableIfNeeded(classId) }.build().also { (it.annotations as MutableList) += context.annotationDeserializer.loadClassAnnotations(classProto, context.nameResolver) } @@ -165,6 +171,19 @@ private val ARRAY_CLASSES: Set = setOf( Name.identifier("BooleanArray"), ) +private val JAVA_IO_SERIALIZABLE = ClassId.topLevel(FqName("java.io.Serializable")) + +private fun AbstractFirRegularClassBuilder.addSerializableIfNeeded(classId: ClassId) { + if (!JvmBuiltInsSettings.isSerializableInJava(classId.asSingleFqName().toUnsafe())) return + superTypeRefs += buildResolvedTypeRef { + type = ConeClassLikeTypeImpl( + ConeClassLikeLookupTagImpl(JAVA_IO_SERIALIZABLE), + typeArguments = emptyArray(), + isNullable = false + ) + } +} + private fun AbstractFirRegularClassBuilder.addCloneForArrayIfNeeded(classId: ClassId) { if (classId.packageFqName != KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME) return if (classId.shortClassName !in ARRAY_CLASSES) return diff --git a/compiler/testData/codegen/box/extensionProperties/genericValMultipleUpperBounds.kt b/compiler/testData/codegen/box/extensionProperties/genericValMultipleUpperBounds.kt index 4fc22da3049..2ac5d0c5790 100644 --- a/compiler/testData/codegen/box/extensionProperties/genericValMultipleUpperBounds.kt +++ b/compiler/testData/codegen/box/extensionProperties/genericValMultipleUpperBounds.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // TARGET_BACKEND: JVM import java.io.Serializable diff --git a/compiler/testData/diagnostics/tests/Serializable.fir.kt b/compiler/testData/diagnostics/tests/Serializable.fir.kt index ee3ba199974..7654789a46d 100644 --- a/compiler/testData/diagnostics/tests/Serializable.fir.kt +++ b/compiler/testData/diagnostics/tests/Serializable.fir.kt @@ -7,32 +7,32 @@ fun useList(s: List) { } fun testPrimitives(b: Byte, ss: Short, i: Int, l: Long, d: Double, s: String, f: Float, bool: Boolean) { - use(b) - use(ss) - use(i) - use(l) - use(s) - use(f) - use(d) - use(bool) + use(b) + use(ss) + use(i) + use(l) + use(s) + use(f) + use(d) + use(bool) } class N class S: java.io.Serializable fun testArrays(ia: IntArray, ai: Array, an: Array, a: Array) { - use(ia) - use(ai) - use(an) - use(a) + use(ia) + use(ai) + use(an) + use(a) } fun testLiterals() { - use(1) - use(1.0) - use(11111111111111) - use("Asdsd") - use(true) + use(1) + use(1.0) + use(11111111111111) + use("Asdsd") + use(true) } fun testNotSerializable(l: List) { @@ -45,11 +45,11 @@ enum class C { } fun testEnums(a: Enum<*>) { - use(C.E) - use(C.E2) - use(a) + use(C.E) + use(C.E2) + use(a) } fun testLists(a: List) { - useList(a) -} \ No newline at end of file + useList(a) +} diff --git a/compiler/testData/diagnostics/tests/j+k/serializable.fir.kt b/compiler/testData/diagnostics/tests/j+k/serializable.fir.kt index f326daf6c9d..33d4685ad52 100644 --- a/compiler/testData/diagnostics/tests/j+k/serializable.fir.kt +++ b/compiler/testData/diagnostics/tests/j+k/serializable.fir.kt @@ -4,32 +4,32 @@ import aa.A.use import aa.A.useList fun testPrimitives(b: Byte, ss: Short, i: Int, l: Long, d: Double, s: String, f: Float, bool: Boolean) { - use(b) - use(ss) - use(i) - use(l) - use(s) - use(f) - use(d) - use(bool) + use(b) + use(ss) + use(i) + use(l) + use(s) + use(f) + use(d) + use(bool) } class N class S: java.io.Serializable fun testArrays(ia: IntArray, ai: Array, an: Array, a: Array) { - use(ia) - use(ai) - use(an) - use(a) + use(ia) + use(ai) + use(an) + use(a) } fun testLiterals() { - use(1) - use(1.0) - use(11111111111111) - use("Asdsd") - use(true) + use(1) + use(1.0) + use(11111111111111) + use("Asdsd") + use(true) } fun testNotSerializable(l: List) { @@ -42,13 +42,13 @@ enum class C { } fun testEnums(a: Enum<*>) { - use(C.E) - use(C.E2) - use(a) + use(C.E) + use(C.E2) + use(a) } fun testLists(a: List) { - useList(a) + useList(a) } // FILE: aa/A.java @@ -57,4 +57,4 @@ package aa; public class A { public static void use(java.io.Serializable s) { } public static void useList(java.util.List s) { } -} \ No newline at end of file +}