diff --git a/compiler/builtins-serializer/src/org/jetbrains/kotlin/serialization/builtins/BuiltInsSerializer.kt b/compiler/builtins-serializer/src/org/jetbrains/kotlin/serialization/builtins/BuiltInsSerializer.kt index d16a7065f5f..7e0b39b655a 100644 --- a/compiler/builtins-serializer/src/org/jetbrains/kotlin/serialization/builtins/BuiltInsSerializer.kt +++ b/compiler/builtins-serializer/src/org/jetbrains/kotlin/serialization/builtins/BuiltInsSerializer.kt @@ -18,6 +18,8 @@ package org.jetbrains.kotlin.serialization.builtins import com.intellij.openapi.util.Disposer import org.jetbrains.kotlin.builtins.BuiltInSerializerProtocol +import org.jetbrains.kotlin.builtins.JvmBuiltInClassDescriptorFactory +import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.messages.* import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles @@ -26,12 +28,16 @@ import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.addKotlinSourceRoots +import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.serialization.MetadataSerializer +import org.jetbrains.kotlin.storage.LockBasedStorageManager import java.io.File class BuiltInsSerializer(dependOnOldBuiltIns: Boolean) : MetadataSerializer(dependOnOldBuiltIns) { @@ -88,11 +94,21 @@ class BuiltInsSerializer(dependOnOldBuiltIns: Boolean) : MetadataSerializer(depe fqName -> val packageView = module.getPackage(fqName) PackageSerializer( - packageView.memberScope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS), + packageView.memberScope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS) + createCloneable(module), packageView.fragments.flatMap { fragment -> DescriptorUtils.getAllDescriptors(fragment.getMemberScope()) }, packageView.fqName, File(destDir, BuiltInSerializerProtocol.getBuiltInsFilePath(packageView.fqName)) ).run() } } + + // Serialize metadata for kotlin.Cloneable manually for compatibility with kotlin-reflect 1.0 which expects this metadata to be there. + // Since Kotlin 1.1, we always discard this class during deserialization (see ClassDeserializer.kt). + private fun createCloneable(module: ModuleDescriptor): ClassDescriptor { + val factory = JvmBuiltInClassDescriptorFactory(LockBasedStorageManager.NO_LOCKS, module) { + EmptyPackageFragmentDescriptor(module, KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME) + } + return factory.createClass(ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.cloneable.toSafe())) + ?: error("Could not create kotlin.Cloneable in $module") + } } diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/jvmDeclarations/cloneable.kt b/compiler/testData/diagnostics/testsWithJsStdLib/jvmDeclarations/cloneable.kt new file mode 100644 index 00000000000..d22a8712898 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/jvmDeclarations/cloneable.kt @@ -0,0 +1,3 @@ +import kotlin.Cloneable + +fun cloneable(): Cloneable = intArrayOf(42) diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/jvmDeclarations/cloneable.txt b/compiler/testData/diagnostics/testsWithJsStdLib/jvmDeclarations/cloneable.txt new file mode 100644 index 00000000000..7b01c793e11 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/jvmDeclarations/cloneable.txt @@ -0,0 +1,3 @@ +package + +public fun cloneable(): [ERROR : Cloneable] diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java index ddd3c0ba440..0e51e5cdda1 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java @@ -369,6 +369,21 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes } } + @TestMetadata("compiler/testData/diagnostics/testsWithJsStdLib/jvmDeclarations") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class JvmDeclarations extends AbstractDiagnosticsTestWithJsStdLib { + public void testAllFilesPresentInJvmDeclarations() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithJsStdLib/jvmDeclarations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("cloneable.kt") + public void testCloneable() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/jvmDeclarations/cloneable.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/diagnostics/testsWithJsStdLib/module") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/builtins/JvmBuiltInClassDescriptorFactory.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/builtins/JvmBuiltInClassDescriptorFactory.kt index de6b96e803e..dc1dbfa6817 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/builtins/JvmBuiltInClassDescriptorFactory.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/builtins/JvmBuiltInClassDescriptorFactory.kt @@ -27,11 +27,14 @@ import org.jetbrains.kotlin.storage.getValue class JvmBuiltInClassDescriptorFactory( storageManager: StorageManager, - private val moduleDescriptor: ModuleDescriptor + private val moduleDescriptor: ModuleDescriptor, + private val computeContainingDeclaration: (ModuleDescriptor) -> DeclarationDescriptor = { module -> + module.getPackage(KOTLIN_FQ_NAME).fragments.filterIsInstance().first() + } ) : ClassDescriptorFactory { private val cloneable by storageManager.createLazyValue { ClassDescriptorImpl( - moduleDescriptor.getPackage(KOTLIN_FQ_NAME).fragments.filterIsInstance().first(), + computeContainingDeclaration(moduleDescriptor), CLONEABLE_NAME, Modality.ABSTRACT, ClassKind.INTERFACE, listOf(moduleDescriptor.builtIns.anyType), SourceElement.NO_SOURCE, /* isExternal = */ false ).apply { diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JvmBuiltInsSettings.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JvmBuiltInsSettings.kt index 4af5a64d5da..39b429ba699 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JvmBuiltInsSettings.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JvmBuiltInsSettings.kt @@ -38,9 +38,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType import org.jetbrains.kotlin.resolve.scopes.MemberScope -import org.jetbrains.kotlin.serialization.deserialization.AdditionalClassPartsProvider -import org.jetbrains.kotlin.serialization.deserialization.PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME -import org.jetbrains.kotlin.serialization.deserialization.PlatformDependentDeclarationFilter +import org.jetbrains.kotlin.serialization.deserialization.* import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.StorageManager @@ -66,7 +64,10 @@ open class JvmBuiltInsSettings( private val mockSerializableType = storageManager.createMockJavaIoSerializableType() private val cloneableType by storageManager.createLazyValue { - moduleDescriptor.builtIns.getBuiltInClassByName(JvmBuiltInClassDescriptorFactory.CLONEABLE_CLASS_ID.shortClassName).defaultType + ownerModuleDescriptor.findNonGenericClassAcrossDependencies( + JvmBuiltInClassDescriptorFactory.CLONEABLE_CLASS_ID, + NotFoundClasses(storageManager, ownerModuleDescriptor) + ).defaultType } private val javaAnalogueClassesWithCustomSupertypeCache = storageManager.createCacheWithNotNullValues() diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/BuiltInsPackageFragment.kt b/core/descriptors/src/org/jetbrains/kotlin/builtins/BuiltInsPackageFragment.kt index cdcaa447cc8..3fcdd8d6aa0 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/BuiltInsPackageFragment.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/BuiltInsPackageFragment.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.builtins import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.serialization.builtins.BuiltInsProtoBuf +import org.jetbrains.kotlin.serialization.deserialization.ClassDeserializer import org.jetbrains.kotlin.serialization.deserialization.DeserializedPackageFragment import org.jetbrains.kotlin.serialization.deserialization.NameResolverImpl import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope @@ -53,6 +54,8 @@ class BuiltInsPackageFragment( override fun computeMemberScope() = DeserializedPackageMemberScope( this, proto.`package`, nameResolver, containerSource = null, components = components, - classNames = { classDataFinder.allClassIds.filter { classId -> !classId.isNestedClass }.map { it.shortClassName } } + classNames = { classDataFinder.allClassIds.filter { classId -> + !classId.isNestedClass && classId !in ClassDeserializer.BLACK_LIST + }.map { it.shortClassName } } ) } diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/ClassDeserializer.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/ClassDeserializer.kt index a40ffa6f2d0..20160369c98 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/ClassDeserializer.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/ClassDeserializer.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.serialization.deserialization +import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.serialization.ClassDataWithSource @@ -36,6 +37,8 @@ class ClassDeserializer(private val components: DeserializationComponents) { for (factory in components.fictitiousClassDescriptorFactories) { factory.createClass(classId)?.let { return it } } + if (classId in BLACK_LIST) return null + val (classData, sourceElement) = key.classDataWithSource ?: components.classDataFinder.findClassData(classId) ?: return null @@ -76,4 +79,16 @@ class ClassDeserializer(private val components: DeserializationComponents) { override fun hashCode() = classId.hashCode() } + + companion object { + /** + * FQ names of classes that should be ignored during deserialization. + * + * We ignore kotlin.Cloneable because since Kotlin 1.1, the descriptor for it is created via JvmBuiltInClassDescriptorFactory, + * but the metadata is still serialized for kotlin-reflect 1.0 to work (see BuiltInsSerializer.kt). + */ + val BLACK_LIST = setOf( + ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.cloneable.toSafe()) + ) + } }