Fix exceptions caused by cyclic dependency between ModuleDescriptor and JvmBuiltIns

^KT-39105 Fixed
^KT-42001 Fixed

See also EA-216604 and EA-211562
This commit is contained in:
Denis.Zharkov
2020-12-22 18:26:52 +03:00
parent 5a8dc00a0d
commit 7b9f6c1560
8 changed files with 90 additions and 48 deletions
@@ -53,25 +53,35 @@ class JvmBuiltIns(storageManager: StorageManager, kind: Kind) : KotlinBuiltIns(s
FALLBACK,
}
// Module containing JDK classes or having them among dependencies
private var ownerModuleDescriptor: ModuleDescriptor? = null
private var isAdditionalBuiltInsFeatureSupported: Boolean = true
class Settings(
// Module containing JDK classes or having them among dependencies
val ownerModuleDescriptor: ModuleDescriptor,
val isAdditionalBuiltInsFeatureSupported: Boolean,
)
private var settingsComputation: (() -> Settings)? = null
fun setPostponedSettingsComputation(computation: () -> Settings) {
assert(settingsComputation == null) { "JvmBuiltins repeated initialization" }
settingsComputation = computation
}
fun initialize(moduleDescriptor: ModuleDescriptor, isAdditionalBuiltInsFeatureSupported: Boolean) {
assert(ownerModuleDescriptor == null) { "JvmBuiltins repeated initialization" }
this.ownerModuleDescriptor = moduleDescriptor
this.isAdditionalBuiltInsFeatureSupported = isAdditionalBuiltInsFeatureSupported
setPostponedSettingsComputation {
Settings(moduleDescriptor, isAdditionalBuiltInsFeatureSupported)
}
}
val customizer: JvmBuiltInsCustomizer by storageManager.createLazyValue {
JvmBuiltInsCustomizer(
builtInsModule, storageManager,
{ ownerModuleDescriptor.sure { "JvmBuiltins has not been initialized properly" } },
{
ownerModuleDescriptor.sure { "JvmBuiltins has not been initialized properly" }
isAdditionalBuiltInsFeatureSupported
}
)
builtInsModule, storageManager
) {
settingsComputation
.sure { "JvmBuiltins instance has not been initialized properly" }
.invoke().also {
settingsComputation = null
}
}
}
init {
@@ -50,19 +50,17 @@ import java.util.*
class JvmBuiltInsCustomizer(
private val moduleDescriptor: ModuleDescriptor,
storageManager: StorageManager,
deferredOwnerModuleDescriptor: () -> ModuleDescriptor,
isAdditionalBuiltInsFeatureSupported: () -> Boolean
settingsComputation: () -> JvmBuiltIns.Settings,
) : AdditionalClassPartsProvider, PlatformDependentDeclarationFilter {
private val j2kClassMapper = JavaToKotlinClassMapper
private val ownerModuleDescriptor: ModuleDescriptor by lazy(deferredOwnerModuleDescriptor)
private val isAdditionalBuiltInsFeatureSupported: Boolean by lazy(isAdditionalBuiltInsFeatureSupported)
private val settings by storageManager.createLazyValue(settingsComputation)
private val mockSerializableType = storageManager.createMockJavaIoSerializableType()
private val cloneableType by storageManager.createLazyValue {
ownerModuleDescriptor.findNonGenericClassAcrossDependencies(
settings.ownerModuleDescriptor.findNonGenericClassAcrossDependencies(
JvmBuiltInClassDescriptorFactory.CLONEABLE_CLASS_ID,
NotFoundClasses(storageManager, ownerModuleDescriptor)
NotFoundClasses(storageManager, settings.ownerModuleDescriptor)
).defaultType
}
@@ -119,7 +117,7 @@ class JvmBuiltInsCustomizer(
)
}
if (!isAdditionalBuiltInsFeatureSupported) return emptyList()
if (!settings.isAdditionalBuiltInsFeatureSupported) return emptyList()
return getAdditionalFunctions(classDescriptor) {
it.getContributedFunctions(name, NoLookupLocation.FROM_BUILTINS)
@@ -158,7 +156,7 @@ class JvmBuiltInsCustomizer(
}
override fun getFunctionsNames(classDescriptor: ClassDescriptor): Set<Name> {
if (!isAdditionalBuiltInsFeatureSupported) return emptySet()
if (!settings.isAdditionalBuiltInsFeatureSupported) return emptySet()
// NB: It's just an approximation that could be calculated relatively fast
// More precise computation would look like `getAdditionalFunctions` (and the measurements show that it would be rather slow)
return classDescriptor.getJavaAnalogue()?.unsubstitutedMemberScope?.getFunctionNames() ?: emptySet()
@@ -270,11 +268,11 @@ class JvmBuiltInsCustomizer(
if (!fqName.isSafe) return null
val javaAnalogueFqName = JavaToKotlinClassMap.mapKotlinToJava(fqName)?.asSingleFqName() ?: return null
return ownerModuleDescriptor.resolveClassByFqName(javaAnalogueFqName, NoLookupLocation.FROM_BUILTINS) as? LazyJavaClassDescriptor
return settings.ownerModuleDescriptor.resolveClassByFqName(javaAnalogueFqName, NoLookupLocation.FROM_BUILTINS) as? LazyJavaClassDescriptor
}
override fun getConstructors(classDescriptor: ClassDescriptor): Collection<ClassConstructorDescriptor> {
if (classDescriptor.kind != ClassKind.CLASS || !isAdditionalBuiltInsFeatureSupported) return emptyList()
if (classDescriptor.kind != ClassKind.CLASS || !settings.isAdditionalBuiltInsFeatureSupported) return emptyList()
val javaAnalogueDescriptor = classDescriptor.getJavaAnalogue() ?: return emptyList()
@@ -317,7 +315,7 @@ class JvmBuiltInsCustomizer(
val javaAnalogueClassDescriptor = classDescriptor.getJavaAnalogue() ?: return true
if (!functionDescriptor.annotations.hasAnnotation(PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME)) return true
if (!isAdditionalBuiltInsFeatureSupported) return false
if (!settings.isAdditionalBuiltInsFeatureSupported) return false
val jvmDescriptor = functionDescriptor.computeJvmDescriptor()
return javaAnalogueClassDescriptor