From 3626008ed266251ccc040f039f9348cbc5dac5fe Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Thu, 18 Feb 2021 17:27:02 +0300 Subject: [PATCH] [Inference] Add ability to approximate local types in AbstractTypeApproximator --- .../kotlin/fir/types/ConeTypeContext.kt | 9 +++++--- .../kotlin/ir/types/IrTypeSystemContext.kt | 7 ++++++- .../kotlin/types/AbstractTypeApproximator.kt | 21 ++++++++++++++++--- .../types/TypeApproximatorConfiguration.kt | 1 + .../kotlin/types/model/TypeSystemContext.kt | 1 + .../types/checker/ClassicTypeSystemContext.kt | 10 +++++---- 6 files changed, 38 insertions(+), 11 deletions(-) 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 647d20f8c14..4740a124e62 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 @@ -21,9 +21,7 @@ import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolved -import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag -import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag -import org.jetbrains.kotlin.fir.symbols.StandardClassIds +import org.jetbrains.kotlin.fir.symbols.* import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqNameUnsafe @@ -44,6 +42,11 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty return this is ConeIntegerLiteralType } + override fun TypeConstructorMarker.isLocalType(): Boolean { + if (this !is ConeClassLikeLookupTag) return false + return classId.isLocal + } + override fun SimpleTypeMarker.possibleIntegerTypes(): Collection { return (this as? ConeIntegerLiteralType)?.possibleTypes ?: emptyList() } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt index 02df059bcd5..900ae060e46 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt @@ -269,6 +269,11 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon override fun TypeConstructorMarker.isIntegerLiteralTypeConstructor() = false + override fun TypeConstructorMarker.isLocalType(): Boolean { + if (this !is IrClassSymbol) return false + return this.owner.classId?.isLocal == true + } + override fun createFlexibleType(lowerBound: SimpleTypeMarker, upperBound: SimpleTypeMarker): KotlinTypeMarker { require(lowerBound.isNothing()) require(upperBound is IrType && upperBound.isNullableAny()) @@ -516,4 +521,4 @@ fun extractTypeParameters(parent: IrDeclarationParent): List { } -class IrTypeSystemContextImpl(override val irBuiltIns: IrBuiltIns) : IrTypeSystemContext \ No newline at end of file +class IrTypeSystemContextImpl(override val irBuiltIns: IrBuiltIns) : IrTypeSystemContext diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/types/AbstractTypeApproximator.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/types/AbstractTypeApproximator.kt index d4c8f0e3d50..f72fdde9826 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/types/AbstractTypeApproximator.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/types/AbstractTypeApproximator.kt @@ -162,6 +162,20 @@ abstract class AbstractTypeApproximator(val ctx: TypeSystemInferenceExtensionCon } } + private fun approximateLocalTypes(type: SimpleTypeMarker, conf: TypeApproximatorConfiguration, toSuper: Boolean): SimpleTypeMarker? { + if (!toSuper) return null + if (!conf.localTypes) return null + val constructor = type.typeConstructor() + val needApproximate = conf.localTypes && constructor.isLocalType() + if (!needApproximate) return null + val superConstructor = constructor.supertypes().first().typeConstructor() + val typeCheckerContext = newBaseTypeCheckerContext( + errorTypesEqualToAnything = false, + stubTypesEqualToAnything = false + ) + return AbstractTypeChecker.findCorrespondingSupertypes(typeCheckerContext, type, superConstructor).first() + } + private fun isIntersectionTypeEffectivelyNothing(constructor: IntersectionTypeConstructorMarker): Boolean { // We consider intersection as Nothing only if one of it's component is a primitive number type // It's intentional we're not trying to prove population of some type as it was in OI @@ -326,7 +340,7 @@ abstract class AbstractTypeApproximator(val ctx: TypeSystemInferenceExtensionCon null } - return null // simple classifier type + return approximateLocalTypes(type, conf, toSuper) // simple classifier type } private fun approximateDefinitelyNotNullType( @@ -518,10 +532,11 @@ abstract class AbstractTypeApproximator(val ctx: TypeSystemInferenceExtensionCon } } - if (newArguments.all { it == null }) return null + if (newArguments.all { it == null }) return approximateLocalTypes(type, conf, toSuper) val newArgumentsList = List(type.argumentsCount()) { index -> newArguments[index] ?: type.getArgument(index) } - return type.replaceArguments(newArgumentsList) + val approximatedType = type.replaceArguments(newArgumentsList) + return approximateLocalTypes(approximatedType, conf, toSuper) ?: approximatedType } private fun KotlinTypeMarker.defaultResult(toSuper: Boolean) = if (toSuper) nullableAnyType() else { diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/types/TypeApproximatorConfiguration.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/types/TypeApproximatorConfiguration.kt index 652f778f88c..ba749411d4d 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/types/TypeApproximatorConfiguration.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/types/TypeApproximatorConfiguration.kt @@ -22,6 +22,7 @@ open class TypeApproximatorConfiguration { open val definitelyNotNullType: Boolean get() = true open val intersection: IntersectionStrategy = IntersectionStrategy.TO_COMMON_SUPERTYPE open val intersectionTypesInContravariantPositions = false + open val localTypes = false open val typeVariable: (TypeVariableTypeConstructorMarker) -> Boolean = { false } open fun capturedType(ctx: TypeSystemInferenceExtensionContext, type: CapturedTypeMarker): Boolean = diff --git a/core/compiler.common/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt b/core/compiler.common/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt index 28051c7825d..9a7ef71838d 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt @@ -304,6 +304,7 @@ interface TypeSystemContext : TypeSystemOptimizationContext { fun TypeConstructorMarker.isIntersection(): Boolean fun TypeConstructorMarker.isClassTypeConstructor(): Boolean fun TypeConstructorMarker.isIntegerLiteralTypeConstructor(): Boolean + fun TypeConstructorMarker.isLocalType(): Boolean fun TypeParameterMarker.getVariance(): TypeVariance fun TypeParameterMarker.upperBoundCount(): Int diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt b/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt index f929d3e2598..3744076f1f4 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt @@ -17,10 +17,7 @@ import org.jetbrains.kotlin.name.FqNameUnsafe import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.calls.inference.CapturedType import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe -import org.jetbrains.kotlin.resolve.descriptorUtil.hasExactAnnotation -import org.jetbrains.kotlin.resolve.descriptorUtil.hasNoInferAnnotation -import org.jetbrains.kotlin.resolve.descriptorUtil.isExactAnnotation +import org.jetbrains.kotlin.resolve.descriptorUtil.* import org.jetbrains.kotlin.resolve.isInlineClass import org.jetbrains.kotlin.resolve.substitutedUnderlyingType import org.jetbrains.kotlin.types.* @@ -42,6 +39,11 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy return this is IntegerLiteralTypeConstructor } + override fun TypeConstructorMarker.isLocalType(): Boolean { + require(this is TypeConstructor, this::errorMessage) + return declarationDescriptor?.classId?.isLocal == true + } + override fun SimpleTypeMarker.possibleIntegerTypes(): Collection { val typeConstructor = typeConstructor() require(typeConstructor is IntegerLiteralTypeConstructor, this::errorMessage)