From be79aeafa71ad499ce794bd1c0c01e9d75c62cdb Mon Sep 17 00:00:00 2001 From: Stanislav Erokhin Date: Wed, 9 Jan 2019 11:03:25 +0300 Subject: [PATCH] Create first draft of AbstractStrictEqualityTypeChecker --- .../AbstractStrictEqualityTypeChecker.kt | 65 +++++++++++++++++++ .../kotlin/types/AbstractTypeChecker.kt | 7 ++ .../kotlin/types/model/TypeSystemContext.kt | 62 ++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 core/type-system/src/org/jetbrains/kotlin/types/AbstractStrictEqualityTypeChecker.kt create mode 100644 core/type-system/src/org/jetbrains/kotlin/types/AbstractTypeChecker.kt create mode 100644 core/type-system/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt diff --git a/core/type-system/src/org/jetbrains/kotlin/types/AbstractStrictEqualityTypeChecker.kt b/core/type-system/src/org/jetbrains/kotlin/types/AbstractStrictEqualityTypeChecker.kt new file mode 100644 index 00000000000..55c411cedf7 --- /dev/null +++ b/core/type-system/src/org/jetbrains/kotlin/types/AbstractStrictEqualityTypeChecker.kt @@ -0,0 +1,65 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.types + +import org.jetbrains.kotlin.types.model.KotlinTypeIM +import org.jetbrains.kotlin.types.model.SimpleTypeIM +import org.jetbrains.kotlin.types.model.TypeSystemContext + +object AbstractStrictEqualityTypeChecker { + fun strictEqualTypes(context: TypeSystemContext, a: KotlinTypeIM, b: KotlinTypeIM) = context.strictEqualTypesInternal(a, b) + + /** + * Note that: + * - `String!` != `String` + * - `A` != `A` + * - `A` != `A` + * - `A<*>` != `A` + * + * Also different error types are not equal even if errorTypeEqualToAnything is true + */ + private fun TypeSystemContext.strictEqualTypesInternal(a: KotlinTypeIM, b: KotlinTypeIM): Boolean { + if (a === b) return true + + val simpleA = a.asSimpleType() + val simpleB = b.asSimpleType() + if (simpleA != null && simpleB != null) return strictEqualSimpleTypes(simpleA, simpleB) + + val flexibleA = a.asFlexibleType() + val flexibleB = b.asFlexibleType() + if (flexibleA != null && flexibleB != null) { + return strictEqualSimpleTypes(flexibleA.lowerBound(), flexibleB.lowerBound()) && + strictEqualSimpleTypes(flexibleA.upperBound(), flexibleB.upperBound()) + } + return false + } + + private fun TypeSystemContext.strictEqualSimpleTypes(a: SimpleTypeIM, b: SimpleTypeIM): Boolean { + if (a.isMarkedNullable() != b.isMarkedNullable() + || (a.asDefinitelyNotNullType() == null) != (b.asDefinitelyNotNullType() == null) + || !isEqualTypeConstructors(a.typeConstructor(), b.typeConstructor()) + || a.argumentsCount() != b.argumentsCount() + ) { + return false + } + +// if (a.arguments === b.arguments) return true + + for (i in 0 until a.argumentsCount()) { + val aArg = a.getArgument(i) + val bArg = b.getArgument(i) + if (aArg.isStarProjection() != bArg.isStarProjection()) return false + + // both non-star + if (!aArg.isStarProjection()) { + if (aArg.getVariance() != bArg.getVariance()) return false + if (!strictEqualTypesInternal(aArg.getType(), bArg.getType())) return false + } + } + return true + } + +} diff --git a/core/type-system/src/org/jetbrains/kotlin/types/AbstractTypeChecker.kt b/core/type-system/src/org/jetbrains/kotlin/types/AbstractTypeChecker.kt new file mode 100644 index 00000000000..de3b1010617 --- /dev/null +++ b/core/type-system/src/org/jetbrains/kotlin/types/AbstractTypeChecker.kt @@ -0,0 +1,7 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.types + diff --git a/core/type-system/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt b/core/type-system/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt new file mode 100644 index 00000000000..91ede9fd571 --- /dev/null +++ b/core/type-system/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.types.model + +interface KotlinTypeIM +interface TypeArgumentIM +interface TypeConstructorIM +interface TypeParameterIM + +interface SimpleTypeIM : KotlinTypeIM +interface CapturedTypeIM : SimpleTypeIM +interface DefinitelyNotNullTypeIM : SimpleTypeIM + +interface FlexibleTypeIM : KotlinTypeIM +interface DynamicTypeIM : FlexibleTypeIM +interface RawTypeIM : FlexibleTypeIM + + +enum class TypeVariance { + IN, + OUT, + INV +} + +interface TypeSystemContext { + fun KotlinTypeIM.asSimpleType(): SimpleTypeIM? + fun KotlinTypeIM.asFlexibleType(): FlexibleTypeIM? + + fun FlexibleTypeIM.asDynamicType(): DynamicTypeIM? + fun FlexibleTypeIM.asRawType(): RawTypeIM? + + fun FlexibleTypeIM.upperBound(): SimpleTypeIM + fun FlexibleTypeIM.lowerBound(): SimpleTypeIM + + fun SimpleTypeIM.asCapturedType(): CapturedTypeIM? + fun SimpleTypeIM.asDefinitelyNotNullType(): DefinitelyNotNullTypeIM? + fun SimpleTypeIM.isMarkedNullable(): Boolean + fun SimpleTypeIM.typeConstructor(): TypeConstructorIM + + fun SimpleTypeIM.argumentsCount(): Int + fun SimpleTypeIM.getArgument(index: Int): TypeArgumentIM + + fun TypeArgumentIM.isStarProjection(): Boolean + fun TypeArgumentIM.getVariance(): TypeVariance + fun TypeArgumentIM.getType(): KotlinTypeIM + + fun TypeConstructorIM.isErrorTypeConstructor(): Boolean + fun TypeConstructorIM.parametersCount(): Int + fun TypeConstructorIM.getParameter(index: Int): TypeParameterIM + fun TypeConstructorIM.supertypesCount(): Int + fun TypeConstructorIM.getSupertype(index: Int): KotlinTypeIM + + fun TypeParameterIM.getVariance(): TypeVariance + fun TypeParameterIM.upperBoundCount(): Int + fun TypeParameterIM.getUpperBound(index: Int): KotlinTypeIM + fun TypeParameterIM.getTypeConstructor(): TypeConstructorIM + + fun isEqualTypeConstructors(c1: TypeConstructorIM, c2: TypeConstructorIM): Boolean +} \ No newline at end of file