Optimize type checking for common cases

- Type equality for simple constructors (no arguments)
- Subtyping on final classes
This commit is contained in:
Denis Zharkov
2017-09-28 18:57:53 +03:00
parent e519095e9e
commit bca53e6c1c
5 changed files with 32 additions and 6 deletions
+1 -1
View File
@@ -3,7 +3,7 @@ package localObjects {
~x~val x : Int
}
class Foo {
open class Foo {
~foo()~fun foo() : Int
}
+1 -1
View File
@@ -1,6 +1,6 @@
package toplevelObjectDeclarations
class Foo(y : Int) {
open class Foo(y : Int) {
~foo()~open fun foo() : Int = 1
}
@@ -40,7 +40,7 @@ fun f_plus(): Int {
1 `contains`!in x
}
~Foo~class Foo {
open ~Foo~class Foo {
~set1~fun set(i : Int, val1 : String) {}
~get1~fun get(i : Int) : Int {}
~get2~fun get(i : Int, j : Int) : String {}
@@ -92,4 +92,4 @@ fun testUnitIncDec() {
var x = UnitIncDec()
x`uinc`++
x`udec`--
}
}
@@ -346,7 +346,7 @@ public class TypeUtils {
}
public static boolean equalTypes(@NotNull KotlinType a, @NotNull KotlinType b) {
return KotlinTypeChecker.DEFAULT.isSubtypeOf(a, b) && KotlinTypeChecker.DEFAULT.isSubtypeOf(b, a);
return KotlinTypeChecker.DEFAULT.equalTypes(a, b);
}
public static boolean dependsOnTypeParameters(@NotNull KotlinType type, @NotNull Collection<TypeParameterDescriptor> typeParameters) {
@@ -18,7 +18,9 @@ package org.jetbrains.kotlin.types.checker
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
import org.jetbrains.kotlin.descriptors.isFinalClass
import org.jetbrains.kotlin.resolve.calls.inference.CapturedType
import org.jetbrains.kotlin.resolve.calls.inference.CapturedTypeConstructor
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstructor
@@ -29,6 +31,7 @@ import org.jetbrains.kotlin.types.checker.TypeCheckerContext.SupertypesPolicy
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
import org.jetbrains.kotlin.types.typeUtil.makeNullable
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
object StrictEqualityTypeChecker {
/**
@@ -91,9 +94,24 @@ object NewKotlinTypeChecker : KotlinTypeChecker {
fun TypeCheckerContext.equalTypes(a: UnwrappedType, b: UnwrappedType): Boolean {
if (a === b) return true
if (isCommonDenotableType(a) && isCommonDenotableType(b)) {
if (!areEqualTypeConstructors(a.constructor, b.constructor)) return false
if (a.arguments.isEmpty()) {
if (a.hasFlexibleNullability() || b.hasFlexibleNullability()) return true
return a.isMarkedNullable == b.isMarkedNullable
}
}
return isSubtypeOf(a, b) && isSubtypeOf(b, a)
}
private fun KotlinType.hasFlexibleNullability() =
lowerIfFlexible().isMarkedNullable != upperIfFlexible().isMarkedNullable
private fun isCommonDenotableType(type: KotlinType) =
type.constructor.isDenotable && !type.isDynamic() && type.lowerIfFlexible().constructor == type.upperIfFlexible().constructor
fun TypeCheckerContext.isSubtypeOf(subType: UnwrappedType, superType: UnwrappedType): Boolean {
val newSubType = transformToNewType(subType)
val newSuperType = transformToNewType(superType)
@@ -266,6 +284,12 @@ object NewKotlinTypeChecker : KotlinTypeChecker {
baseType: SimpleType,
constructor: TypeConstructor
): List<SimpleType> {
if (constructor.declarationDescriptor.safeAs<ClassDescriptor>()?.isCommonFinalClass == true) {
return if (areEqualTypeConstructors(baseType.constructor, constructor))
listOf(captureFromArguments(baseType, CaptureStatus.FOR_SUBTYPING) ?: baseType)
else
emptyList()
}
var result: MutableList<SimpleType>? = null
@@ -293,6 +317,9 @@ object NewKotlinTypeChecker : KotlinTypeChecker {
return result ?: emptyList()
}
private val ClassDescriptor.isCommonFinalClass: Boolean
get() = isFinalClass && kind != ClassKind.ENUM_ENTRY
/**
* If we have several paths to some interface, we should prefer pure kotlin path.
* Example:
@@ -357,7 +384,6 @@ object NewKotlinTypeChecker : KotlinTypeChecker {
}
object NullabilityChecker {
// this method checks only nullability