Disable slow assertions in type checker everywhere except for tests

This commit is contained in:
Denis Zharkov
2019-06-14 16:06:52 +03:00
parent 46d8f45c11
commit fdebb38706
6 changed files with 68 additions and 27 deletions
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.w3c.dom.Node
import org.w3c.dom.NodeList
import java.io.File
@@ -32,6 +33,16 @@ private fun NodeList.toList(): List<Node> {
private val Node.childNodesList get() = childNodes.toList()
abstract class AbstractModularizedTest : KtUsefulTestCase() {
override fun setUp() {
super.setUp()
AbstractTypeChecker.RUN_SLOW_ASSERTIONS = false
}
override fun tearDown() {
super.tearDown()
AbstractTypeChecker.RUN_SLOW_ASSERTIONS = true
}
private fun loadModule(file: File): ModuleData {
val factory = DocumentBuilderFactory.newInstance()
@@ -92,4 +103,4 @@ abstract class AbstractModularizedTest : KtUsefulTestCase() {
afterPass()
}
}
}
@@ -253,6 +253,7 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck
AbstractTypeChecker.isSubtypeOf(this as AbstractTypeCheckerContext, subType, superType)
private fun assertInputTypes(subType: KotlinTypeMarker, superType: KotlinTypeMarker) {
if (!AbstractTypeChecker.RUN_SLOW_ASSERTIONS) return
fun correctSubType(subType: SimpleTypeMarker) =
subType.isSingleClassifierType() || subType.typeConstructor().isIntersection() || isMyTypeVariable(subType) || subType.isError() || subType.isIntegerLiteralType()
@@ -278,4 +279,4 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck
is FlexibleTypeMarker -> f(lowerBound()) || f(upperBound())
else -> error("sealed")
}
}
}
@@ -88,13 +88,15 @@ interface NewTypeSubstitutor: TypeSubstitutorMarker {
"original lower type: '${capturedType.lowerType}"
)
typeConstructor.supertypes.forEach { supertype ->
substitute(supertype, keepAnnotation, runCapturedChecks = false)?.let {
throw IllegalStateException(
"Illegal type substitutor: $this, " +
"because for captured type '$type' supertype approximation should be null, but it is: '$supertype'," +
"original supertype: '$supertype'"
)
if (AbstractTypeChecker.RUN_SLOW_ASSERTIONS) {
typeConstructor.supertypes.forEach { supertype ->
substitute(supertype, keepAnnotation, runCapturedChecks = false)?.let {
throw IllegalStateException(
"Illegal type substitutor: $this, " +
"because for captured type '$type' supertype approximation should be null, but it is: '$supertype'," +
"original supertype: '$supertype'"
)
}
}
}
@@ -178,4 +180,4 @@ class FreshVariableNewTypeSubstitutor(val freshVariables: List<TypeVariableFromC
fun UnwrappedType.substituteTypeVariable(typeVariable: NewTypeVariable, value: UnwrappedType): UnwrappedType {
val substitutor = NewTypeSubstitutorByConstructorMap(mapOf(typeVariable.freshTypeConstructor to value))
return substitutor.safeSubstitute(this)
}
}
@@ -16,8 +16,6 @@
package org.jetbrains.kotlin.test.testFramework;
import com.intellij.codeInsight.CodeInsightSettings;
import com.intellij.concurrency.IdeaForkJoinWorkerThreadFactory;
import com.intellij.diagnostic.PerformanceWatcher;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.Application;
@@ -51,6 +49,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.test.IdeaSystemPropertiesForParallelRunConfigurator;
import org.jetbrains.kotlin.testFramework.MockComponentManagerCreationTracer;
import org.jetbrains.kotlin.types.AbstractTypeChecker;
import org.jetbrains.kotlin.types.FlexibleTypeImpl;
import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
import org.junit.Assert;
@@ -100,6 +99,7 @@ public abstract class KtUsefulTestCase extends TestCase {
System.setProperty("apple.awt.UIElement", "true");
FlexibleTypeImpl.RUN_SLOW_ASSERTIONS = true;
AbstractTypeChecker.RUN_SLOW_ASSERTIONS = true;
}
protected boolean shouldContainTempFiles() {
@@ -981,4 +981,4 @@ public abstract class KtUsefulTestCase extends TestCase {
return KtUsefulTestCase.this.getClass() + (StringUtil.isEmpty(testName) ? "" : ".test" + testName);
}
};
}
}
@@ -18,11 +18,15 @@ package org.jetbrains.kotlin.jvm.compiler
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.test.KotlinTestWithEnvironmentManagement
import org.jetbrains.kotlin.types.AbstractNullabilityChecker
import org.jetbrains.kotlin.types.KotlinTypeFactory
import org.jetbrains.kotlin.types.SimpleType
import org.jetbrains.kotlin.types.TypeIntersector
import org.jetbrains.kotlin.types.checker.ClassicTypeCheckerContext
class FlexibleTypeAssertionsEnabledTest : KotlinTestWithEnvironmentManagement() {
class SlowTypeAssertionsEnabledTest : KotlinTestWithEnvironmentManagement() {
fun testAssertionsAreOn() {
fun testAssertionsForFlexibleTypesAreOn() {
val builtIns = DefaultBuiltIns.Instance
try {
@@ -34,4 +38,21 @@ class FlexibleTypeAssertionsEnabledTest : KotlinTestWithEnvironmentManagement()
fail("Assertion error expected")
}
fun testAssertionsForTypeCheckerAreOn() {
val builtIns = DefaultBuiltIns.Instance
try {
val superType = TypeIntersector.intersectTypes(listOf(builtIns.charSequence.defaultType, builtIns.comparable.defaultType))
AbstractNullabilityChecker.isPossibleSubtype(
ClassicTypeCheckerContext(errorTypeEqualsToAnything = true), builtIns.annotationType,
superType as SimpleType
)
} catch (e: AssertionError) {
assertEquals("Not singleClassifierType superType: {CharSequence & Comparable<T>}", e.message)
return
}
fail("Assertion error expected")
}
}
@@ -144,6 +144,8 @@ abstract class AbstractTypeCheckerContext : TypeSystemContext {
}
object AbstractTypeChecker {
@JvmField
var RUN_SLOW_ASSERTIONS = false
fun isSubtypeOf(context: TypeCheckerProviderContext, subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean {
return AbstractTypeChecker.isSubtypeOf(context.newBaseTypeCheckerContext(true), subType, superType)
@@ -223,11 +225,13 @@ object AbstractTypeChecker {
}
private fun AbstractTypeCheckerContext.isSubtypeOfForSingleClassifierType(subType: SimpleTypeMarker, superType: SimpleTypeMarker): Boolean {
assert(subType.isSingleClassifierType() || subType.typeConstructor().isIntersection() || subType.isAllowedTypeVariable) {
"Not singleClassifierType and not intersection subType: $subType"
}
assert(superType.isSingleClassifierType() || superType.isAllowedTypeVariable) {
"Not singleClassifierType superType: $superType"
if (AbstractTypeChecker.RUN_SLOW_ASSERTIONS) {
assert(subType.isSingleClassifierType() || subType.typeConstructor().isIntersection() || subType.isAllowedTypeVariable) {
"Not singleClassifierType and not intersection subType: $subType"
}
assert(superType.isSingleClassifierType() || superType.isAllowedTypeVariable) {
"Not singleClassifierType superType: $superType"
}
}
if (!AbstractNullabilityChecker.isPossibleSubtype(this, subType, superType)) return false
@@ -469,12 +473,14 @@ object AbstractNullabilityChecker {
}
private fun AbstractTypeCheckerContext.runIsPossibleSubtype(subType: SimpleTypeMarker, superType: SimpleTypeMarker): Boolean {
// it makes for case String? & Any <: String
assert(subType.isSingleClassifierType() || subType.typeConstructor().isIntersection() || subType.isAllowedTypeVariable) {
"Not singleClassifierType and not intersection subType: $subType"
}
assert(superType.isSingleClassifierType() || superType.isAllowedTypeVariable) {
"Not singleClassifierType superType: $superType"
if (AbstractTypeChecker.RUN_SLOW_ASSERTIONS) {
// it makes for case String? & Any <: String
assert(subType.isSingleClassifierType() || subType.typeConstructor().isIntersection() || subType.isAllowedTypeVariable) {
"Not singleClassifierType and not intersection subType: $subType"
}
assert(superType.isSingleClassifierType() || superType.isAllowedTypeVariable) {
"Not singleClassifierType superType: $superType"
}
}
// superType is actually nullable
@@ -525,4 +531,4 @@ object AbstractNullabilityChecker {
}) {
if (it.isMarkedNullable()) SupertypesPolicy.None else SupertypesPolicy.LowerIfFlexible
}
}
}