From e4938c6c36a154cbdacd1c0cd363d1da85e8796a Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Thu, 29 Aug 2019 11:22:05 +0300 Subject: [PATCH] [FIR] Remove status map from intersection type --- .../jetbrains/kotlin/fir/types/ConeTypes.kt | 37 ++----------- .../kotlin/fir/resolve/ResolveUtils.kt | 4 +- .../resolve/substitution/ConeSubstitutor.kt | 2 +- .../kotlin/fir/types/ConeTypeContext.kt | 15 +++--- .../kotlin/fir/types/ConeTypeIntersector.kt | 52 ++++--------------- 5 files changed, 25 insertions(+), 85 deletions(-) diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt index 98e101ab2b4..b493e9a35b9 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt @@ -182,44 +182,15 @@ class ConeDefinitelyNotNullType(val original: ConeKotlinType): ConeKotlinType(), * only via ConeTypeIntersector */ class ConeIntersectionType( - val constructor: ConeIntersectionTypeConstructor -) : ConeKotlinType(), SimpleTypeMarker { + val intersectedTypes: Collection +) : ConeKotlinType(), SimpleTypeMarker, TypeConstructorMarker { override val typeArguments: Array get() = emptyArray() override val nullability: ConeNullability get() = ConeNullability.NOT_NULL - - val intersectedTypes: Collection get() = constructor.intersectedTypes - val statusMap: Map get() = constructor.statusMap } -class ConeIntersectionTypeConstructor( - val intersectedTypes: Collection, - val statusMap: Map -) : TypeConstructorMarker { - val supertypes: Collection get() = intersectedTypes - - /* - * IMPORTANT: use this method only for types from intersectedTypes - */ - fun getStatus(type: ConeKotlinType): IntersectionStatus { - return statusMap[type] ?: error("") - } - - enum class IntersectionStatus { - FROM_INFERENCE, - FROM_SMARTCAST - } -} - -fun ConeIntersectionTypeConstructor.mapTypes(func: (ConeKotlinType) -> ConeKotlinType): ConeIntersectionTypeConstructor { - val newStatusMap = mutableMapOf() - val newTypes = intersectedTypes.map { type -> - val newType = func(type) - // TODO: what if some types squash? What status should we choose? - newStatusMap[newType] = getStatus(type) - newType - } - return ConeIntersectionTypeConstructor(newTypes, newStatusMap) +fun ConeIntersectionType.mapTypes(func: (ConeKotlinType) -> ConeKotlinType): ConeIntersectionType { + return ConeIntersectionType(intersectedTypes.map(func)) } \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt index 024b9a969de..5749375fe25 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt @@ -164,9 +164,9 @@ fun T.withNullability(nullability: ConeNullability): T { is ConeTypeVariableType -> ConeTypeVariableType(nullability, lookupTag) as T is ConeCapturedType -> ConeCapturedType(captureStatus, lowerType, nullability, constructor) as T is ConeIntersectionType -> when (nullability) { - ConeNullability.NULLABLE -> ConeIntersectionType(constructor.mapTypes { + ConeNullability.NULLABLE -> this.mapTypes { it.withNullability(nullability) - }) + } ConeNullability.UNKNOWN -> this // TODO: is that correct? ConeNullability.NOT_NULL -> this } as T diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/substitution/ConeSubstitutor.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/substitution/ConeSubstitutor.kt index 1f031204198..16b8650be71 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/substitution/ConeSubstitutor.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/substitution/ConeSubstitutor.kt @@ -89,7 +89,7 @@ abstract class AbstractConeSubstitutor : ConeSubstitutor() { substitutedTypes += substitutedType } if (!somethingIsSubstituted) return null - return ConeIntersectionType(ConeIntersectionTypeConstructor(substitutedTypes, statusMap)) + return ConeIntersectionType(substitutedTypes) } private fun ConeDefinitelyNotNullType.substituteOriginal(): ConeDefinitelyNotNullType? { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt index 42c9e972533..f0e6192da91 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.expandedConeType import org.jetbrains.kotlin.fir.declarations.superConeTypes import org.jetbrains.kotlin.fir.resolve.* +import org.jetbrains.kotlin.fir.resolve.calls.ConeInferenceContext import org.jetbrains.kotlin.fir.resolve.calls.ConeTypeVariableTypeConstructor import org.jetbrains.kotlin.fir.resolve.calls.hasNullableSuperType import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor @@ -141,7 +142,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty is ConeAbbreviatedType -> this.directExpansionType(session)?.typeConstructor() ?: ErrorTypeConstructor("Failed to expand alias: ${this}") is ConeLookupTagBasedType -> this.lookupTag.toSymbol(session) ?: ErrorTypeConstructor("Unresolved: ${this.lookupTag}") - is ConeIntersectionType -> constructor + is ConeIntersectionType -> this else -> error("?: ${this}") } @@ -206,7 +207,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty is ConeCapturedTypeConstructor, is ErrorTypeConstructor, is ConeTypeVariableTypeConstructor, - is ConeIntersectionTypeConstructor -> 0 + is ConeIntersectionType -> 0 is FirClassSymbol -> fir.typeParameters.size is FirTypeAliasSymbol -> fir.typeParameters.size else -> error("?!:10") @@ -232,13 +233,13 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty is FirClassSymbol -> fir.superConeTypes is FirTypeAliasSymbol -> listOfNotNull(fir.expandedConeType) is ConeCapturedTypeConstructor -> supertypes!! - is ConeIntersectionTypeConstructor -> intersectedTypes + is ConeIntersectionType -> intersectedTypes else -> error("?!:13") } } override fun TypeConstructorMarker.isIntersection(): Boolean { - return this is ConeIntersectionTypeConstructor + return this is ConeIntersectionType } override fun TypeConstructorMarker.isClassTypeConstructor(): Boolean { @@ -279,7 +280,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty return when (this) { is ConeCapturedTypeConstructor, is ConeTypeVariableTypeConstructor, - is ConeIntersectionTypeConstructor -> false + is ConeIntersectionType -> false is ConeSymbol -> true else -> true } @@ -381,12 +382,12 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty override fun intersectTypes(types: List): SimpleTypeMarker { @Suppress("UNCHECKED_CAST") - return ConeTypeIntersector.intersectTypes(this, types as List) as SimpleTypeMarker + return ConeTypeIntersector.intersectTypes(this as ConeInferenceContext, types as List) as SimpleTypeMarker } override fun intersectTypes(types: List): KotlinTypeMarker { @Suppress("UNCHECKED_CAST") - return ConeTypeIntersector.intersectTypes(this, types as List) + return ConeTypeIntersector.intersectTypes(this as ConeInferenceContext, types as List) } private fun prepareClassLikeType( diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeIntersector.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeIntersector.kt index 4fb1baf0f75..bcc511793f4 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeIntersector.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeIntersector.kt @@ -6,32 +6,22 @@ package org.jetbrains.kotlin.fir.types import org.jetbrains.kotlin.fir.resolve.calls.ConeInferenceContext -import org.jetbrains.kotlin.fir.types.ConeIntersectionTypeConstructor.IntersectionStatus import org.jetbrains.kotlin.types.AbstractTypeChecker import java.util.* import kotlin.collections.LinkedHashSet object ConeTypeIntersector { - fun intersectTypes(context: ConeTypeContext, types: List): ConeKotlinType { - require(context is ConeInferenceContext) - return intersectTypes(context, types, types.map { IntersectionStatus.FROM_INFERENCE }) - } - - private fun intersectTypes( + fun intersectTypes( context: ConeInferenceContext, - types: List, - intersectionStatus: List + types: List ): ConeKotlinType { - assert(types.size == intersectionStatus.size) - when (types.size) { 0 -> error("Expected some types") 1 -> return types.single() } val inputTypes = mutableListOf() - val statusMap = mutableMapOf() - flatIntersectionTypes(types, intersectionStatus, inputTypes, statusMap) + flatIntersectionTypes(types, inputTypes) /** * resultNullability. Value description: @@ -49,19 +39,16 @@ object ConeTypeIntersector { val inputTypesWithCorrectNullability = inputTypes.mapTo(LinkedHashSet()) { if (resultNullability == ResultNullability.NOT_NULL) with(context) { - val resultType = it.makeDefinitelyNotNullOrNotNull() as ConeKotlinType - statusMap[resultType] = statusMap.remove(it)!! - resultType + it.makeDefinitelyNotNullOrNotNull() as ConeKotlinType } else it } - return intersectTypesWithoutIntersectionType(context, inputTypesWithCorrectNullability, statusMap) + return intersectTypesWithoutIntersectionType(context, inputTypesWithCorrectNullability) } private fun intersectTypesWithoutIntersectionType( context: ConeTypeContext, - inputTypes: Set, - statusMap: MutableMap + inputTypes: Set ): ConeKotlinType { if (inputTypes.size == 1) return inputTypes.single().type @@ -81,7 +68,7 @@ object ConeTypeIntersector { * We want to drop A from that set, because it's useless for type checking. But in case if * A came from inference and B came from smartcast we want to safe both types in intersection */ - isStrictSupertype(context, lower, upper) && statusMap[lower]!! <= statusMap[upper]!! + isStrictSupertype(context, lower, upper) } assert(filteredEqualTypes.isNotEmpty(), errorMessage) @@ -95,11 +82,7 @@ object ConeTypeIntersector { if (filteredSuperAndEqualTypes.size < 2) return filteredSuperAndEqualTypes.single() - val constructor = ConeIntersectionTypeConstructor( - filteredSuperAndEqualTypes, - filteredSuperAndEqualTypes.associateWithTo(mutableMapOf()) { statusMap[it]!! } - ) - return ConeIntersectionType(constructor) + return ConeIntersectionType(filteredSuperAndEqualTypes) } private fun filterTypes( @@ -123,32 +106,17 @@ object ConeTypeIntersector { } } - @Suppress("NOTHING_TO_INLINE") - private inline fun MutableMap.updateStatus(type: ConeKotlinType, status: IntersectionStatus) { - // We should keep status FROM_SMARTCAST for correct diagnostic reporting - val existingStatus = get(type) - if (existingStatus == null) { - put(type, status) - } else { - put(type, minOf(status, existingStatus)) - } - } - private fun flatIntersectionTypes( inputTypes: List, - intersectionStatus: List, - typeCollector: MutableList, - statusMap: MutableMap + typeCollector: MutableList ) { - for ((inputType, status) in inputTypes.zip(intersectionStatus)) { + for (inputType in inputTypes) { if (inputType is ConeIntersectionType) { for (type in inputType.intersectedTypes) { typeCollector += type - statusMap.updateStatus(type, status) } } else { typeCollector += inputType - statusMap.updateStatus(inputType, status) } } }