From 25a168d2a4f2beac35fd13fea08cf86d47d98858 Mon Sep 17 00:00:00 2001 From: Stanislav Erokhin Date: Fri, 30 Oct 2015 19:40:45 +0300 Subject: [PATCH] Minor. Fix potential deadlock --- .../jetbrains/kotlin/types/flexibleTypes.kt | 35 +++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/flexibleTypes.kt b/core/descriptors/src/org/jetbrains/kotlin/types/flexibleTypes.kt index cfa307ac139..e9600044d42 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/flexibleTypes.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/flexibleTypes.kt @@ -129,6 +129,26 @@ public open class DelegatingFlexibleType protected constructor( } } + // These assertions are needed for checking invariants of flexible types. + // + // Unfortunately isSubtypeOf is running resolve for lazy types. + // Because of this we can't run these assertions when we are creating this type. See EA-74904 + // + // Also isSubtypeOf is not a very fast operation, so we are running assertions only if ASSERTIONS_ENABLED. See KT-7540 + private var assertionsDone = false + + private fun runAssertions() { + if (assertionsDone || !ASSERTIONS_ENABLED) return + assertionsDone = true + + assert (!lowerBound.isFlexible()) { "Lower bound of a flexible type can not be flexible: $lowerBound" } + assert (!upperBound.isFlexible()) { "Upper bound of a flexible type can not be flexible: $upperBound" } + assert (lowerBound != upperBound) { "Lower and upper bounds are equal: $lowerBound == $upperBound" } + assert (KotlinTypeChecker.DEFAULT.isSubtypeOf(lowerBound, upperBound)) { + "Lower bound $lowerBound of a flexible type must be a subtype of the upper bound $upperBound" + } + } + override fun getCapability(capabilityClass: Class): T? { val extra = extraCapabilities.getCapability(capabilityClass, this, this) if (extra != null) return extra @@ -150,17 +170,10 @@ public open class DelegatingFlexibleType protected constructor( override fun isMarkedNullable(): Boolean = getCapability(javaClass())!!.computeIsNullable() - override val delegateType: KotlinType by lazy { - // we can't check this in init block, because lowerBound & upperBound can be LazyType. see EA-74904 - if (ASSERTIONS_ENABLED) { // workaround for KT-7540 - assert (!lowerBound.isFlexible()) { "Lower bound of a flexible type can not be flexible: $lowerBound" } - assert (!upperBound.isFlexible()) { "Upper bound of a flexible type can not be flexible: $upperBound" } - assert (lowerBound != upperBound) { "Lower and upper bounds are equal: $lowerBound == $upperBound" } - assert (KotlinTypeChecker.DEFAULT.isSubtypeOf(lowerBound, upperBound)) { - "Lower bound $lowerBound of a flexible type must be a subtype of the upper bound $upperBound" - } - } - lowerBound + override val delegateType: KotlinType + get() { + runAssertions() + return lowerBound } override fun getDelegate() = getCapability(javaClass())!!.delegateType