[Core API] Introduce TypeConstructor.refine
This commit introduces TypeConstructor.refine method. It's implementation can be roughly split in three parts: - trivial implementations which just return 'this': mostly, it used for typeConstructors which can not be refined at all (e.g. IntegerValueTypeConstructor and other special cases of constructors) - delegating implementations which call 'refine' recursively for component typeConstructors -- obviously, they are used in composite typeConstructors (like IntersectionTypeConstructor) - finally, the most interesting one is in 'AbstractTypeConstructor' which returns lightweight wrapper called 'ModuleViewTypeConstructor'. The idea here is to propagate refinement to supertypes without eagerly computing them all. VERY IMPORTANT CAVEAT of TypeConstructor.refine is that call to this method CAN NOT add new supertypes, so returned supertypes are not entirely "valid". See the KDoc for TypeConstructor.refine for details
This commit is contained in:
+5
@@ -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 {
|
||||
|
||||
+5
@@ -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)"
|
||||
}
|
||||
|
||||
|
||||
+5
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+4
@@ -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(
|
||||
|
||||
+12
-7
@@ -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<KotlinType>()
|
||||
|
||||
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<TypeParameterDescriptor> = 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() }}]"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
-4
@@ -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)"
|
||||
}
|
||||
|
||||
|
||||
@@ -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<TypeParameterDescriptor> = this@AbstractTypeConstructor.parameters
|
||||
|
||||
override fun getSupertypes(): List<KotlinType> = 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)
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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<KotlinType>) : TypeConstructor {
|
||||
@@ -67,6 +69,10 @@ class IntersectionTypeConstructor(typesToIntersect: Collection<KotlinType>) : Ty
|
||||
)
|
||||
|
||||
override fun hashCode(): Int = hashCode
|
||||
|
||||
@TypeRefinement
|
||||
override fun refine(kotlinTypeRefiner: KotlinTypeRefiner) =
|
||||
IntersectionTypeConstructor(intersectedTypes.map { it.refine(kotlinTypeRefiner) })
|
||||
}
|
||||
|
||||
inline fun IntersectionTypeConstructor.transformComponents(
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user