diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceUtil.kt index ad49be73958..b7583d0b14b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceUtil.kt @@ -40,10 +40,12 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE import org.jetbrains.kotlin.types.checker.ClassicTypeCheckerContext +import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo import org.jetbrains.kotlin.types.model.KotlinTypeMarker +import org.jetbrains.kotlin.types.refinement.TypeRefinement import org.jetbrains.kotlin.types.typeUtil.* import javax.inject.Inject @@ -64,6 +66,9 @@ class TypeTemplate( override fun render(renderer: DescriptorRenderer, options: DescriptorRendererOptions) = "~${renderer.renderType(typeVariable.type)}" + + @TypeRefinement + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner) = this } class CoroutineInferenceData { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/TypeVariable.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/TypeVariable.kt index 973578518c8..0c83fe044ff 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/TypeVariable.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/TypeVariable.kt @@ -27,8 +27,10 @@ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinTypeFactory import org.jetbrains.kotlin.types.SimpleType import org.jetbrains.kotlin.types.TypeConstructor +import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner import org.jetbrains.kotlin.types.checker.NewTypeVariableConstructor import org.jetbrains.kotlin.types.model.TypeVariableMarker +import org.jetbrains.kotlin.types.refinement.TypeRefinement class TypeVariableTypeConstructor(private val builtIns: KotlinBuiltIns, val debugName: String) : TypeConstructor, @@ -41,6 +43,9 @@ class TypeVariableTypeConstructor(private val builtIns: KotlinBuiltIns, val debu override fun getBuiltIns() = builtIns + @TypeRefinement + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner): TypeConstructor = this + override fun toString() = "TypeVariable($debugName)" } diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeAliasDescriptor.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeAliasDescriptor.kt index 66acd73396d..74473890d7f 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeAliasDescriptor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeAliasDescriptor.kt @@ -112,5 +112,10 @@ abstract class AbstractTypeAliasDescriptor( declarationDescriptor.builtIns override fun toString(): String = "[typealias ${declarationDescriptor.name.asString()}]" + + // There must be @TypeRefinement, but there is a bug with anonymous objects and experimental annotations + // See KT-31728 + @UseExperimental(TypeRefinement::class) + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner): TypeConstructor? = this } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/CapturedTypeConstructor.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/CapturedTypeConstructor.kt index d06a1e53ed5..04a4f973e91 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/CapturedTypeConstructor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/CapturedTypeConstructor.kt @@ -62,6 +62,10 @@ class CapturedTypeConstructorImpl( override fun toString() = "CapturedTypeConstructor($projection)" override fun getBuiltIns(): KotlinBuiltIns = projection.type.constructor.builtIns + + @TypeRefinement + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner) = + CapturedTypeConstructorImpl(projection.refine(kotlinTypeRefiner)) } class CapturedType( diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/IntegerLiteralTypeConstructor.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/IntegerLiteralTypeConstructor.kt index 8df527713c0..4a6122f19b7 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/IntegerLiteralTypeConstructor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/IntegerLiteralTypeConstructor.kt @@ -11,7 +11,8 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.types.* -import java.lang.IllegalStateException +import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner +import org.jetbrains.kotlin.types.refinement.TypeRefinement class IntegerLiteralTypeConstructor : TypeConstructor { companion object { @@ -64,7 +65,7 @@ class IntegerLiteralTypeConstructor : TypeConstructor { private fun fold(left: IntegerLiteralTypeConstructor, right: SimpleType): SimpleType? = if (right in left.possibleTypes) right else null - + } private val value: Long @@ -74,7 +75,7 @@ class IntegerLiteralTypeConstructor : TypeConstructor { constructor(value: Long, module: ModuleDescriptor, parameters: CompileTimeConstant.Parameters) { this.value = value this.module = module - + val possibleTypes = mutableSetOf() fun checkBoundsAndAddPossibleType(value: Long, kotlinType: KotlinType) { @@ -143,15 +144,15 @@ class IntegerLiteralTypeConstructor : TypeConstructor { builtIns.longType in possibleTypes -> builtIns.longType builtIns.byteType in possibleTypes -> builtIns.byteType builtIns.shortType in possibleTypes -> builtIns.shortType - + module.uIntType in possibleTypes -> module.uIntType module.uLongType in possibleTypes -> module.uLongType module.uByteType in possibleTypes -> module.uByteType module.uShortType in possibleTypes -> module.uShortType - + else -> throw IllegalStateException() } - + override fun getParameters(): List = emptyList() @@ -165,6 +166,9 @@ class IntegerLiteralTypeConstructor : TypeConstructor { override fun getBuiltIns(): KotlinBuiltIns = module.builtIns + @TypeRefinement + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner): TypeConstructor = this + override fun toString(): String { return "IntegerLiteralType${valueToString()}" } @@ -172,4 +176,5 @@ class IntegerLiteralTypeConstructor : TypeConstructor { fun checkConstructor(constructor: TypeConstructor): Boolean = possibleTypes.any { it.constructor == constructor } private fun valueToString(): String = "[${possibleTypes.joinToString(",") { it.toString() }}]" -} \ No newline at end of file + +} diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/IntegerValueTypeConstructor.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/IntegerValueTypeConstructor.kt index 8add786a3ae..17ac74326df 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/IntegerValueTypeConstructor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/IntegerValueTypeConstructor.kt @@ -17,14 +17,12 @@ package org.jetbrains.kotlin.resolve.constants import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.builtins.UnsignedTypes import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor -import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies -import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.SimpleType import org.jetbrains.kotlin.types.TypeConstructor +import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner +import org.jetbrains.kotlin.types.refinement.TypeRefinement import java.util.* class IntegerValueTypeConstructor( @@ -95,6 +93,9 @@ class IntegerValueTypeConstructor( return module.builtIns } + @TypeRefinement + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner): TypeConstructor = this + override fun toString() = "IntegerValueType($value)" } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/AbstractTypeConstructor.kt b/core/descriptors/src/org/jetbrains/kotlin/types/AbstractTypeConstructor.kt index 1a37d4f799e..b0425c938f3 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/AbstractTypeConstructor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/AbstractTypeConstructor.kt @@ -16,12 +16,58 @@ package org.jetbrains.kotlin.types -import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.storage.StorageManager +import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner +import org.jetbrains.kotlin.types.checker.refineTypes +import org.jetbrains.kotlin.types.refinement.TypeRefinement abstract class AbstractTypeConstructor(storageManager: StorageManager) : TypeConstructor { override fun getSupertypes() = supertypes().supertypesWithoutCycles + abstract override fun getDeclarationDescriptor(): ClassifierDescriptor + + @TypeRefinement + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner): TypeConstructor = ModuleViewTypeConstructor(kotlinTypeRefiner) + + @TypeRefinement + private inner class ModuleViewTypeConstructor( + private val kotlinTypeRefiner: KotlinTypeRefiner + ) : TypeConstructor { + /* NB: it is important to use PUBLICATION here instead of 'storageManager.createLazyValue { ... }' + + The reason is that 'storageManager' can be a storage manager from DefaultBuiltIns (e.g. is this type constructor + is type constructor of some built-in class like 'Int'). Therefore, call to refined supertypes would result in + the following order of acquiring locks: DefaultBuiltIns lock -> Sources lock + + Obviously, a lot of code acquires locks in different order (sources lock first, then built-ins lock), so that would + result in deadlock + */ + private val refinedSupertypes by lazy(LazyThreadSafetyMode.PUBLICATION) { + @UseExperimental(TypeRefinement::class) + kotlinTypeRefiner.refineTypes(this@AbstractTypeConstructor.getSupertypes()) + } + + override fun getParameters(): List = this@AbstractTypeConstructor.parameters + + override fun getSupertypes(): List = refinedSupertypes + + override fun isFinal(): Boolean = this@AbstractTypeConstructor.isFinal + override fun isDenotable(): Boolean = this@AbstractTypeConstructor.isDenotable + + override fun getDeclarationDescriptor() = this@AbstractTypeConstructor.declarationDescriptor + + override fun getBuiltIns(): KotlinBuiltIns = this@AbstractTypeConstructor.builtIns + + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner): TypeConstructor = + this@AbstractTypeConstructor.refine(kotlinTypeRefiner) + + override fun equals(other: Any?) = this@AbstractTypeConstructor.equals(other) + override fun hashCode() = this@AbstractTypeConstructor.hashCode() + override fun toString() = this@AbstractTypeConstructor.toString() + } + // In current version diagnostic about loops in supertypes is reported on each vertex (supertype reference) that lies on the cycle. // To achieve that we store both versions of supertypes --- before and after loops disconnection. // The first one is used for computation of neighbours in supertypes graph (see Companion.computeNeighbours) diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/ErrorUtils.java b/core/descriptors/src/org/jetbrains/kotlin/types/ErrorUtils.java index ec66fbc6f06..4c1adc37fc1 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/ErrorUtils.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/ErrorUtils.java @@ -523,6 +523,13 @@ public class ErrorUtils { public String toString() { return debugName; } + + @TypeRefinement + @Override + @NotNull + public TypeConstructor refine(@NotNull KotlinTypeRefiner kotlinTypeRefiner) { + return this; + } }; } @@ -615,6 +622,12 @@ public class ErrorUtils { public KotlinBuiltIns getBuiltIns() { return DescriptorUtilsKt.getBuiltIns(typeParameterDescriptor); } + + @NotNull + @Override + public TypeConstructor refine(@NotNull KotlinTypeRefiner kotlinTypeRefiner) { + return this; + } } private ErrorUtils() {} diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/FunctionPlaceholders.kt b/core/descriptors/src/org/jetbrains/kotlin/types/FunctionPlaceholders.kt index b248787e467..0579da2b481 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/FunctionPlaceholders.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/FunctionPlaceholders.kt @@ -19,6 +19,8 @@ package org.jetbrains.kotlin.types import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.ClassifierDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner +import org.jetbrains.kotlin.types.refinement.TypeRefinement class FunctionPlaceholders(private val builtIns: KotlinBuiltIns) { fun createFunctionPlaceholderType( @@ -71,4 +73,7 @@ class FunctionPlaceholderTypeConstructor( override fun getBuiltIns(): KotlinBuiltIns { return kotlinBuiltIns } + + @TypeRefinement + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner): TypeConstructor = this } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/IntersectionTypeConstructor.kt b/core/descriptors/src/org/jetbrains/kotlin/types/IntersectionTypeConstructor.kt index fb66f13d1fc..533cc63f58c 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/IntersectionTypeConstructor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/IntersectionTypeConstructor.kt @@ -22,6 +22,8 @@ import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.TypeIntersectionScope +import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner +import org.jetbrains.kotlin.types.refinement.TypeRefinement import java.util.* class IntersectionTypeConstructor(typesToIntersect: Collection) : TypeConstructor { @@ -67,6 +69,10 @@ class IntersectionTypeConstructor(typesToIntersect: Collection) : Ty ) override fun hashCode(): Int = hashCode + + @TypeRefinement + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner) = + IntersectionTypeConstructor(intersectedTypes.map { it.refine(kotlinTypeRefiner) }) } inline fun IntersectionTypeConstructor.transformComponents( diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeConstructor.java b/core/descriptors/src/org/jetbrains/kotlin/types/TypeConstructor.java index 39dce87095b..9b08a4d2b9c 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeConstructor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeConstructor.java @@ -22,7 +22,9 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.descriptors.ClassifierDescriptor; import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor; +import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner; import org.jetbrains.kotlin.types.model.TypeConstructorMarker; +import org.jetbrains.kotlin.types.refinement.TypeRefinement; import java.util.Collection; import java.util.List; @@ -58,4 +60,27 @@ public interface TypeConstructor extends TypeConstructorMarker { @NotNull KotlinBuiltIns getBuiltIns(); + + /** + * Returns TypeConstructor, refined with passed refined, if that makes sense for this specific typeConstructor + * + * Contract: + * - returned TypeConstructor has refined supertypes, i.e. it has correct supertypes resolved as if + * we were looking at them from refiner's module + * - IT DOES NOT ADD PLATFORM DECLARED SUPERTYPES!!!!!!!! + * - all other similar sources of KotlinTypes/Descriptors should return refined instances as well + * + * That method is part of internal refinement infrastructure, so IT SHOULD NOT BE CALLED from anywhere except + * methods from refinement (like methods of KotlinTypeRefinerImpl or KotlinType.refine + * + * Implementation notice: + * - the most interesting part happens in 'AbstractTypeConstructor': it returns 'ModuleViewTypeConstructor', which + * will refine supertypes when queried for them + * - also, there are several typeConstructors, which do not inherit AbstractTypeConstructor, but have some component + * types/descriptors (e.g. IntersectionTypeConstructor) -- they refine their content manually by recursing using refiner + * - finally, most special typeConstructors have no meaningful refinement and return null (i.e. UninferredTypeParameterConstructor) + */ + @TypeRefinement + @NotNull + TypeConstructor refine(@NotNull KotlinTypeRefiner kotlinTypeRefiner); } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewCapturedType.kt b/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewCapturedType.kt index d8bacde6526..94da3aa9416 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewCapturedType.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewCapturedType.kt @@ -158,5 +158,9 @@ class NewCapturedTypeConstructor(override val projection: TypeProjection, privat override fun getDeclarationDescriptor(): ClassifierDescriptor? = null override fun getBuiltIns(): KotlinBuiltIns = projection.type.builtIns + @TypeRefinement + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner) = + NewCapturedTypeConstructor(projection.refine(kotlinTypeRefiner), supertypes?.map { it.refine(kotlinTypeRefiner) }) + override fun toString() = "CapturedType($projection)" }