Abstract NewInference & related from KotlinType

Cleanup TypeConstructors & KotlinTypes in VariableFixationFinder
Cleanup TypeConstructors & KotlinTypes in TypeVariableDirectionCalculator
Cleanup KotlinTypes in TypeCheckerContext for ConstraintSystem
Cleanup KotlinTypes in NewCommonSuperTypeCalculator
Cleanup KotlinTypes in TypeApproximator
Cleanup type substitution
Cleanup NewTypeVariable
Cleanup StubType
Cleanup TypeCheckerContext creation, extract common supertype context
Provide TypeSystemInferenceExtensionContext via dependency injection
This commit is contained in:
Simon Ogorodnik
2019-02-18 20:19:33 +03:00
parent 0ffded5bac
commit 3998e842f1
47 changed files with 1347 additions and 661 deletions
@@ -333,6 +333,23 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext {
symbol is FirTypeParameterSymbol symbol is FirTypeParameterSymbol
} }
override fun intersectTypes(types: List<KotlinTypeMarker>): KotlinTypeMarker {
TODO("not implemented")
}
override fun intersectTypes(types: List<SimpleTypeMarker>): SimpleTypeMarker {
TODO("not implemented")
}
override fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker {
TODO("not implemented")
}
override fun SimpleTypeMarker.isStubType(): Boolean {
TODO("not implemented")
}
} }
@@ -359,4 +376,8 @@ class ConeTypeCheckerContext(override val isErrorTypeEqualsToAnything: Boolean,
get() = false get() = false
override fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker {
return super<ConeTypeContext>.prepareType(type)
}
} }
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.calls.components.ClassicTypeSystemContextForCS
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactoryImpl import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactoryImpl
import org.jetbrains.kotlin.resolve.calls.tower.KotlinResolutionStatelessCallbacksImpl import org.jetbrains.kotlin.resolve.calls.tower.KotlinResolutionStatelessCallbacksImpl
import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker
@@ -72,6 +73,7 @@ private fun StorageComponentContainer.configurePlatformIndependentComponents() {
useImpl<ExperimentalUsageChecker>() useImpl<ExperimentalUsageChecker>()
useImpl<ExperimentalUsageChecker.Overrides>() useImpl<ExperimentalUsageChecker.Overrides>()
useImpl<ExperimentalUsageChecker.ClassifierUsage>() useImpl<ExperimentalUsageChecker.ClassifierUsage>()
useImpl<ClassicTypeSystemContextForCS>()
} }
fun StorageComponentContainer.configureModule( fun StorageComponentContainer.configureModule(
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.resolve.constants.CompileTimeConstantChecker
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class DiagnosticReporterByTrackingStrategy( class DiagnosticReporterByTrackingStrategy(
@@ -212,19 +213,19 @@ class DiagnosticReporterByTrackingStrategy(
val expression = it.psiExpression ?: return val expression = it.psiExpression ?: return
val deparenthesized = KtPsiUtil.safeDeparenthesize(expression) val deparenthesized = KtPsiUtil.safeDeparenthesize(expression)
if (reportConstantTypeMismatch(constraintError, deparenthesized)) return if (reportConstantTypeMismatch(constraintError, deparenthesized)) return
trace.report(Errors.TYPE_MISMATCH.on(deparenthesized, constraintError.upperType, constraintError.lowerType)) trace.report(Errors.TYPE_MISMATCH.on(deparenthesized, constraintError.upperKotlinType, constraintError.lowerKotlinType))
} }
(position as? ExpectedTypeConstraintPosition)?.let { (position as? ExpectedTypeConstraintPosition)?.let {
val call = it.topLevelCall.psiKotlinCall.psiCall.callElement.safeAs<KtExpression>() val call = it.topLevelCall.psiKotlinCall.psiCall.callElement.safeAs<KtExpression>()
reportIfNonNull(call) { reportIfNonNull(call) {
trace.report(Errors.TYPE_MISMATCH.on(it, constraintError.upperType, constraintError.lowerType)) trace.report(Errors.TYPE_MISMATCH.on(it, constraintError.upperKotlinType, constraintError.lowerKotlinType))
} }
} }
(position as? ExplicitTypeParameterConstraintPosition)?.let { (position as? ExplicitTypeParameterConstraintPosition)?.let {
val typeArgumentReference = (it.typeArgument as SimpleTypeArgumentImpl).typeReference val typeArgumentReference = (it.typeArgument as SimpleTypeArgumentImpl).typeReference
trace.report(UPPER_BOUND_VIOLATED.on(typeArgumentReference, constraintError.upperType, constraintError.lowerType)) trace.report(UPPER_BOUND_VIOLATED.on(typeArgumentReference, constraintError.upperKotlinType, constraintError.lowerKotlinType))
} }
} }
CapturedTypeFromSubtyping::class.java -> { CapturedTypeFromSubtyping::class.java -> {
@@ -247,10 +248,14 @@ class DiagnosticReporterByTrackingStrategy(
val module = context.scope.ownerDescriptor.module val module = context.scope.ownerDescriptor.module
val constantValue = constantExpressionEvaluator.evaluateToConstantValue(expression, trace, context.expectedType) val constantValue = constantExpressionEvaluator.evaluateToConstantValue(expression, trace, context.expectedType)
val hasConstantTypeError = CompileTimeConstantChecker(context, module, true) val hasConstantTypeError = CompileTimeConstantChecker(context, module, true)
.checkConstantExpressionType(constantValue, expression, constraintError.upperType) .checkConstantExpressionType(constantValue, expression, constraintError.upperKotlinType)
if (hasConstantTypeError) return true if (hasConstantTypeError) return true
} }
return false return false
} }
} }
val NewConstraintError.upperKotlinType get() = upperType as KotlinType
val NewConstraintError.lowerKotlinType get() = lowerType as KotlinType
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace import org.jetbrains.kotlin.resolve.TemporaryBindingTrace
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
import org.jetbrains.kotlin.resolve.calls.components.CompletedCallInfo import org.jetbrains.kotlin.resolve.calls.components.CompletedCallInfo
import org.jetbrains.kotlin.resolve.calls.components.NewConstraintSystemImpl
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter
@@ -29,6 +30,7 @@ import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.expressions.DoubleColonExpressionResolver import org.jetbrains.kotlin.types.expressions.DoubleColonExpressionResolver
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
import org.jetbrains.kotlin.utils.addToStdlib.cast
class CoroutineInferenceSession( class CoroutineInferenceSession(
psiCallResolver: PSICallResolver, psiCallResolver: PSICallResolver,
@@ -88,7 +90,7 @@ class CoroutineInferenceSession(
updateCalls(lambda, commonSystem) updateCalls(lambda, commonSystem)
return commonSystem.fixedTypeVariables return commonSystem.fixedTypeVariables.cast() // TODO: SUB
} }
private fun createNonFixedTypeToVariableSubstitutor(): NewTypeSubstitutorByConstructorMap { private fun createNonFixedTypeToVariableSubstitutor(): NewTypeSubstitutorByConstructorMap {
@@ -117,8 +119,8 @@ class CoroutineInferenceSession(
val callSubstitutor = storage.buildResultingSubstitutor() // substitutor only for fixed variables val callSubstitutor = storage.buildResultingSubstitutor() // substitutor only for fixed variables
for (initialConstraint in storage.initialConstraints) { for (initialConstraint in storage.initialConstraints) {
val lower = nonFixedToVariablesSubstitutor.safeSubstitute(callSubstitutor.safeSubstitute(initialConstraint.a)) val lower = nonFixedToVariablesSubstitutor.safeSubstitute(callSubstitutor.safeSubstitute(initialConstraint.a as UnwrappedType)) // TODO: SUB
val upper = nonFixedToVariablesSubstitutor.safeSubstitute(callSubstitutor.safeSubstitute(initialConstraint.b)) val upper = nonFixedToVariablesSubstitutor.safeSubstitute(callSubstitutor.safeSubstitute(initialConstraint.b as UnwrappedType)) // TODO: SUB
if (commonSystem.isProperType(lower) && commonSystem.isProperType(upper)) continue if (commonSystem.isProperType(lower) && commonSystem.isProperType(upper)) continue
@@ -183,9 +185,9 @@ class CoroutineInferenceSession(
nonFixedTypesToResult: Map<TypeConstructor, UnwrappedType> nonFixedTypesToResult: Map<TypeConstructor, UnwrappedType>
) { ) {
val resultingCallSubstitutor = completedCall.callResolutionResult.constraintSystem.fixedTypeVariables.entries val resultingCallSubstitutor = completedCall.callResolutionResult.constraintSystem.fixedTypeVariables.entries
.associate { it.key to nonFixedTypesToResultSubstitutor.safeSubstitute(it.value) } .associate { it.key to nonFixedTypesToResultSubstitutor.safeSubstitute(it.value as UnwrappedType) } // TODO: SUB
val resultingSubstitutor = NewTypeSubstitutorByConstructorMap(resultingCallSubstitutor + nonFixedTypesToResult) val resultingSubstitutor = NewTypeSubstitutorByConstructorMap((resultingCallSubstitutor + nonFixedTypesToResult).cast()) // TODO: SUB
val atomCompleter = createResolvedAtomCompleter(resultingSubstitutor, completedCall.context) val atomCompleter = createResolvedAtomCompleter(resultingSubstitutor, completedCall.context)
val resultCallAtom = completedCall.callResolutionResult.resultCallAtom val resultCallAtom = completedCall.callResolutionResult.resultCallAtom
@@ -665,7 +665,9 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
typeArguments = resolvedCallAtom.substitutor.freshVariables.map { typeArguments = resolvedCallAtom.substitutor.freshVariables.map {
val substituted = (substitutor ?: FreshVariableNewTypeSubstitutor.Empty).safeSubstitute(it.defaultType) val substituted = (substitutor ?: FreshVariableNewTypeSubstitutor.Empty).safeSubstitute(it.defaultType)
TypeApproximator().approximateToSuperType(substituted, TypeApproximatorConfiguration.CapturedAndIntegerLiteralsTypesApproximation) ?: substituted TypeApproximator(substituted.constructor.builtIns)
.approximateToSuperType(substituted, TypeApproximatorConfiguration.CapturedAndIntegerLiteralsTypesApproximation)
?: substituted
} }
calculateExpedtedTypeForSamConvertedArgumentMap(substitutor) calculateExpedtedTypeForSamConvertedArgumentMap(substitutor)
@@ -134,7 +134,7 @@ class ResolvedAtomCompleter(
} }
val approximatedReturnType = val approximatedReturnType =
TypeApproximator().approximateDeclarationType( TypeApproximator(builtIns).approximateDeclarationType(
returnType, returnType,
local = true, local = true,
languageVersionSettings = topLevelCallContext.languageVersionSettings languageVersionSettings = topLevelCallContext.languageVersionSettings
@@ -28,7 +28,7 @@ internal val jvmCoercionToUnitPhase = makeIrFilePhase(
class JvmCoercionToUnitPatcher(val context: JvmBackendContext) : class JvmCoercionToUnitPatcher(val context: JvmBackendContext) :
InsertImplicitCasts( InsertImplicitCasts(
context.builtIns, context.irBuiltIns, context.builtIns, context.irBuiltIns,
TypeTranslator(context.ir.symbols.externalSymbolTable, context.state.languageVersionSettings), TypeTranslator(context.ir.symbols.externalSymbolTable, context.state.languageVersionSettings, context.builtIns),
JvmGeneratorExtensions.samConversion JvmGeneratorExtensions.samConversion
), ),
FileLoweringPass { FileLoweringPass {
@@ -40,7 +40,7 @@ class GeneratorContext(
) : IrGeneratorContext() { ) : IrGeneratorContext() {
val constantValueGenerator: ConstantValueGenerator = ConstantValueGenerator(moduleDescriptor, symbolTable) val constantValueGenerator: ConstantValueGenerator = ConstantValueGenerator(moduleDescriptor, symbolTable)
val typeTranslator: TypeTranslator = TypeTranslator(symbolTable, languageVersionSettings) val typeTranslator: TypeTranslator = TypeTranslator(symbolTable, languageVersionSettings, builtIns = moduleDescriptor.builtIns)
init { init {
typeTranslator.constantValueGenerator = constantValueGenerator typeTranslator.constantValueGenerator = constantValueGenerator
@@ -45,7 +45,7 @@ class DeclarationStubGenerator(
} }
private val typeTranslator = TypeTranslator(lazyTable, languageVersionSettings, LazyScopedTypeParametersResolver(lazyTable), true) private val typeTranslator = TypeTranslator(lazyTable, languageVersionSettings, moduleDescriptor.builtIns, LazyScopedTypeParametersResolver(lazyTable), true)
private val constantValueGenerator = ConstantValueGenerator(moduleDescriptor, lazyTable) private val constantValueGenerator = ConstantValueGenerator(moduleDescriptor, lazyTable)
init { init {
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.ir.util package org.jetbrains.kotlin.ir.util
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
@@ -25,11 +26,12 @@ import org.jetbrains.kotlin.types.typesApproximation.approximateCapturedTypes
class TypeTranslator( class TypeTranslator(
private val symbolTable: ReferenceSymbolTable, private val symbolTable: ReferenceSymbolTable,
val languageVersionSettings: LanguageVersionSettings, val languageVersionSettings: LanguageVersionSettings,
builtIns: KotlinBuiltIns,
private val typeParametersResolver: TypeParametersResolver = ScopedTypeParametersResolver(), private val typeParametersResolver: TypeParametersResolver = ScopedTypeParametersResolver(),
private val enterTableScope: Boolean = false private val enterTableScope: Boolean = false
) { ) {
private val typeApproximatorForNI = TypeApproximator() private val typeApproximatorForNI = TypeApproximator(builtIns)
lateinit var constantValueGenerator: ConstantValueGenerator lateinit var constantValueGenerator: ConstantValueGenerator
fun enterScope(irElement: IrTypeParametersContainer) { fun enterScope(irElement: IrTypeParametersContainer) {
@@ -124,7 +126,11 @@ class TypeTranslator(
if (ktType.constructor.isDenotable) return ktType if (ktType.constructor.isDenotable) return ktType
return if (languageVersionSettings.supportsFeature(LanguageFeature.NewInference)) return if (languageVersionSettings.supportsFeature(LanguageFeature.NewInference))
typeApproximatorForNI.approximateDeclarationType(ktType, local = false, languageVersionSettings = languageVersionSettings) typeApproximatorForNI.approximateDeclarationType(
ktType,
local = false,
languageVersionSettings = languageVersionSettings
)
else else
approximateCapturedTypes(ktType).upper approximateCapturedTypes(ktType).upper
} }
@@ -21,17 +21,24 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.* import org.jetbrains.kotlin.types.checker.*
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection import org.jetbrains.kotlin.types.AbstractNullabilityChecker.hasPathByNotMarkedNullableNodes
import org.jetbrains.kotlin.types.typeUtil.canHaveUndefinedNullability import org.jetbrains.kotlin.types.model.*
object NewCommonSuperTypeCalculator { object NewCommonSuperTypeCalculator {
// TODO: Bridge for old calls
fun commonSuperType(types: List<UnwrappedType>): UnwrappedType { fun commonSuperType(types: List<UnwrappedType>): UnwrappedType {
val ctx = object : ClassicTypeSystemContext {}
return ctx.commonSuperType(types) as UnwrappedType
}
fun TypeSystemCommonSuperTypesContext.commonSuperType(types: List<KotlinTypeMarker>): KotlinTypeMarker {
val maxDepth = types.maxBy { it.typeDepth() }?.typeDepth() ?: 0 val maxDepth = types.maxBy { it.typeDepth() }?.typeDepth() ?: 0
return commonSuperType(types, -maxDepth) return commonSuperType(types, -maxDepth)
} }
private fun commonSuperType(types: List<UnwrappedType>, depth: Int): UnwrappedType { private fun TypeSystemCommonSuperTypesContext.commonSuperType(types: List<KotlinTypeMarker>, depth: Int): KotlinTypeMarker {
if (types.isEmpty()) throw IllegalStateException("Empty collection for input") if (types.isEmpty()) throw IllegalStateException("Empty collection for input")
types.singleOrNull()?.let { return it } types.singleOrNull()?.let { return it }
@@ -40,49 +47,57 @@ object NewCommonSuperTypeCalculator {
val lowers = types.map { val lowers = types.map {
when (it) { when (it) {
is SimpleType -> it is SimpleTypeMarker -> it
is FlexibleType -> { is FlexibleTypeMarker -> {
if (it is DynamicType) return it if (it.isDynamic()) return it
// raw types are allowed here and will be transformed to FlexibleTypes // raw types are allowed here and will be transformed to FlexibleTypes
thereIsFlexibleTypes = true thereIsFlexibleTypes = true
it.lowerBound it.lowerBound()
} }
else -> error("sealed")
} }
} }
val lowerSuperType = commonSuperTypeForSimpleTypes(lowers, depth) val lowerSuperType = commonSuperTypeForSimpleTypes(lowers, depth)
if (!thereIsFlexibleTypes) return lowerSuperType if (!thereIsFlexibleTypes) return lowerSuperType
val upperSuperType = commonSuperTypeForSimpleTypes(types.map { it.upperIfFlexible() }, depth) val upperSuperType = commonSuperTypeForSimpleTypes(types.map { it.upperBoundIfFlexible() }, depth)
return KotlinTypeFactory.flexibleType(lowerSuperType, upperSuperType) return createFlexibleType(lowerSuperType, upperSuperType)
} }
private fun commonSuperTypeForSimpleTypes(types: List<SimpleType>, depth: Int): SimpleType { private fun TypeSystemCommonSuperTypesContext.commonSuperTypeForSimpleTypes(
types: List<SimpleTypeMarker>,
depth: Int
): SimpleTypeMarker {
// i.e. result type also should be marked nullable // i.e. result type also should be marked nullable
val notAllNotNull = types.any { !NullabilityChecker.isSubtypeOfAny(it) } val notAllNotNull = types.any { !AbstractNullabilityChecker.isSubtypeOfAny(this, it) }
val notNullTypes = if (notAllNotNull) types.map { it.makeNullableAsSpecified(false) } else types val notNullTypes = if (notAllNotNull) types.map { it.withNullability(false) } else types
val commonSuperType = commonSuperTypeForNotNullTypes(notNullTypes, depth) val commonSuperType = commonSuperTypeForNotNullTypes(notNullTypes, depth)
return if (notAllNotNull) return if (notAllNotNull)
refineNullabilityForUndefinedNullability(types, commonSuperType) ?: commonSuperType.makeNullableAsSpecified(true) refineNullabilityForUndefinedNullability(types, commonSuperType) ?: commonSuperType.withNullability(true)
else else
commonSuperType commonSuperType
} }
private fun refineNullabilityForUndefinedNullability(types: List<SimpleType>, commonSuperType: SimpleType): SimpleType? { private fun TypeSystemCommonSuperTypesContext.refineNullabilityForUndefinedNullability(
if (!commonSuperType.unwrap().canHaveUndefinedNullability()) return null types: List<SimpleTypeMarker>,
commonSuperType: SimpleTypeMarker
): SimpleTypeMarker? {
if (!commonSuperType.canHaveUndefinedNullability()) return null
val actuallyNotNull = types.all { NullabilityChecker.hasPathByNotMarkedNullableNodes(it, commonSuperType.constructor) } val actuallyNotNull =
types.all { hasPathByNotMarkedNullableNodes(it, commonSuperType.typeConstructor()) }
return if (actuallyNotNull) commonSuperType else null return if (actuallyNotNull) commonSuperType else null
} }
// Makes representative sample, i.e. (A, B, A) -> (A, B) // Makes representative sample, i.e. (A, B, A) -> (A, B)
private fun List<SimpleType>.uniquify(): List<SimpleType> { private fun TypeSystemCommonSuperTypesContext.uniquify(types: List<SimpleTypeMarker>): List<SimpleTypeMarker> {
val uniqueTypes = arrayListOf<SimpleType>() val uniqueTypes = arrayListOf<SimpleTypeMarker>()
for (type in this) { for (type in types) {
val isNewUniqueType = uniqueTypes.all { val isNewUniqueType = uniqueTypes.all {
!NewKotlinTypeChecker.equalTypes(it, type) || it.constructor is IntegerLiteralTypeConstructor !AbstractTypeChecker.equalTypes(this, it, type) || it.typeConstructor().isIntegerLiteralTypeConstructor()
} }
if (isNewUniqueType) { if (isNewUniqueType) {
uniqueTypes += type uniqueTypes += type
@@ -93,13 +108,13 @@ object NewCommonSuperTypeCalculator {
// This function leaves only supertypes, i.e. A0 is a strong supertype for A iff A != A0 && A <: A0 // This function leaves only supertypes, i.e. A0 is a strong supertype for A iff A != A0 && A <: A0
// Explanation: consider types (A : A0, B : B0, A0, B0), then CST(A, B, A0, B0) == CST(CST(A, A0), CST(B, B0)) == CST(A0, B0) // Explanation: consider types (A : A0, B : B0, A0, B0), then CST(A, B, A0, B0) == CST(CST(A, A0), CST(B, B0)) == CST(A0, B0)
private fun List<SimpleType>.filterSupertypes(): List<SimpleType> { private fun TypeSystemCommonSuperTypesContext.filterSupertypes(list: List<SimpleTypeMarker>): List<SimpleTypeMarker> {
val supertypes = this.toMutableList() val supertypes = list.toMutableList()
val iterator = supertypes.iterator() val iterator = supertypes.iterator()
while (iterator.hasNext()) { while (iterator.hasNext()) {
val potentialSubtype = iterator.next() val potentialSubtype = iterator.next()
val isSubtype = supertypes.any { supertype -> val isSubtype = supertypes.any { supertype ->
supertype !== potentialSubtype && NewKotlinTypeChecker.isSubtypeOf(potentialSubtype, supertype) supertype !== potentialSubtype && AbstractTypeChecker.isSubtypeOf(this, potentialSubtype, supertype)
} }
if (isSubtype) iterator.remove() if (isSubtype) iterator.remove()
@@ -108,28 +123,35 @@ object NewCommonSuperTypeCalculator {
return supertypes return supertypes
} }
private fun commonSuperTypeForNotNullTypes(types: List<SimpleType>, depth: Int): SimpleType { private fun TypeSystemCommonSuperTypesContext.commonSuperTypeForNotNullTypes(
types: List<SimpleTypeMarker>,
depth: Int
): SimpleTypeMarker {
if (types.size == 1) return types.single() if (types.size == 1) return types.single()
val uniqueTypes = types.uniquify() val uniqueTypes = uniquify(types)
if (uniqueTypes.size == 1) return uniqueTypes.single() if (uniqueTypes.size == 1) return uniqueTypes.single()
val explicitSupertypes = uniqueTypes.filterSupertypes() val explicitSupertypes = filterSupertypes(uniqueTypes)
if (explicitSupertypes.size == 1) return explicitSupertypes.single() if (explicitSupertypes.size == 1) return explicitSupertypes.single()
IntegerLiteralTypeConstructor.findCommonSuperType(explicitSupertypes)?.let { return it } findCommonIntegerLiteralTypesSuperType(explicitSupertypes)?.let { return it }
// IntegerLiteralTypeConstructor.findCommonSuperType(explicitSupertypes)?.let { return it }
return findSuperTypeConstructorsAndIntersectResult(explicitSupertypes, depth) return findSuperTypeConstructorsAndIntersectResult(explicitSupertypes, depth)
} }
private fun findSuperTypeConstructorsAndIntersectResult(types: List<SimpleType>, depth: Int): SimpleType { private fun TypeSystemCommonSuperTypesContext.findSuperTypeConstructorsAndIntersectResult(
types: List<SimpleTypeMarker>,
depth: Int
): SimpleTypeMarker {
return intersectTypes(allCommonSuperTypeConstructors(types).map { superTypeWithGivenConstructor(types, it, depth) }) return intersectTypes(allCommonSuperTypeConstructors(types).map { superTypeWithGivenConstructor(types, it, depth) })
} }
/** /**
* Note that if there is captured type C, then no one else is not subtype of C => lowerType cannot help here * Note that if there is captured type C, then no one else is not subtype of C => lowerType cannot help here
*/ */
private fun allCommonSuperTypeConstructors(types: List<SimpleType>): List<TypeConstructor> { private fun TypeSystemCommonSuperTypesContext.allCommonSuperTypeConstructors(types: List<SimpleTypeMarker>): List<TypeConstructorMarker> {
val result = collectAllSupertypes(types.first()) val result = collectAllSupertypes(types.first())
for (type in types) { for (type in types) {
if (type === types.first()) continue if (type === types.first()) continue
@@ -138,22 +160,22 @@ object NewCommonSuperTypeCalculator {
} }
return result.filterNot { target -> return result.filterNot { target ->
result.any { other -> result.any { other ->
other != target && other.supertypes.any { it.constructor == target } other != target && other.supertypes().any { it.typeConstructor() == target }
} }
} }
} }
private fun collectAllSupertypes(type: SimpleType) = LinkedHashSet<TypeConstructor>().apply { private fun TypeSystemCommonSuperTypesContext.collectAllSupertypes(type: SimpleTypeMarker) =
type.anySuperTypeConstructor { add(it); false } LinkedHashSet<TypeConstructorMarker>().apply {
} type.anySuperTypeConstructor { add(it); false }
}
private fun superTypeWithGivenConstructor( private fun TypeSystemCommonSuperTypesContext.superTypeWithGivenConstructor(
types: List<SimpleType>, types: List<SimpleTypeMarker>,
constructor: TypeConstructor, constructor: TypeConstructorMarker,
depth: Int depth: Int
): SimpleType { ): SimpleTypeMarker {
if (constructor.parameters.isEmpty()) return KotlinTypeFactory.simpleType( if (constructor.parametersCount() == 0) return createSimpleType(
Annotations.EMPTY,
constructor, constructor,
emptyList(), emptyList(),
nullable = false nullable = false
@@ -168,17 +190,18 @@ object NewCommonSuperTypeCalculator {
* but it is too complicated and we will return not so accurate type: CS(List<Int>, List<Double>, List<String>) * but it is too complicated and we will return not so accurate type: CS(List<Int>, List<Double>, List<String>)
*/ */
val correspondingSuperTypes = types.flatMap { val correspondingSuperTypes = types.flatMap {
with(NewKotlinTypeChecker) { with(AbstractTypeChecker) {
typeCheckerContext.findCorrespondingSupertypes(it, constructor) typeCheckerContext.findCorrespondingSupertypes(it, constructor)
} }
} }
val arguments = ArrayList<TypeProjection>(constructor.parameters.size) val arguments = ArrayList<TypeArgumentMarker>(constructor.parametersCount())
for ((index, parameter) in constructor.parameters.withIndex()) { for (index in 0 until constructor.parametersCount()) {
val parameter = constructor.getParameter(index)
var thereIsStar = false var thereIsStar = false
val typeProjections = correspondingSuperTypes.mapNotNull { val typeProjections = correspondingSuperTypes.mapNotNull {
it.arguments.getOrNull(index)?.let { it.getArgumentOrNull(index)?.let {
if (it.isStarProjection) { if (it.isStarProjection()) {
thereIsStar = true thereIsStar = true
null null
} else it } else it
@@ -187,38 +210,42 @@ object NewCommonSuperTypeCalculator {
val argument = val argument =
if (thereIsStar || typeProjections.isEmpty()) { if (thereIsStar || typeProjections.isEmpty()) {
StarProjectionImpl(parameter) createStarProjection(parameter)
} else { } else {
calculateArgument(parameter, typeProjections, depth) calculateArgument(parameter, typeProjections, depth)
} }
arguments.add(argument) arguments.add(argument)
} }
return KotlinTypeFactory.simpleType(Annotations.EMPTY, constructor, arguments, nullable = false) return createSimpleType(constructor, arguments, nullable = false)
} }
// no star projections in arguments // no star projections in arguments
private fun calculateArgument(parameter: TypeParameterDescriptor, arguments: List<TypeProjection>, depth: Int): TypeProjection { private fun TypeSystemCommonSuperTypesContext.calculateArgument(
parameter: TypeParameterMarker,
arguments: List<TypeArgumentMarker>,
depth: Int
): TypeArgumentMarker {
if (depth > 3) { if (depth > 3) {
return StarProjectionImpl(parameter) return createStarProjection(parameter)
} }
// Inv<A>, Inv<A> = Inv<A> // Inv<A>, Inv<A> = Inv<A>
if (parameter.variance == Variance.INVARIANT && arguments.all { it.projectionKind == Variance.INVARIANT }) { if (parameter.getVariance() == TypeVariance.INV && arguments.all { it.getVariance() == TypeVariance.INV }) {
val first = arguments.first() val first = arguments.first()
if (arguments.all { it.type == first.type }) return first if (arguments.all { it.getType() == first.getType() }) return first
} }
val asOut: Boolean val asOut: Boolean
if (parameter.variance != Variance.INVARIANT) { if (parameter.getVariance() != TypeVariance.INV) {
asOut = parameter.variance == Variance.OUT_VARIANCE asOut = parameter.getVariance() == TypeVariance.OUT
} else { } else {
val thereIsOut = arguments.any { it.projectionKind == Variance.OUT_VARIANCE } val thereIsOut = arguments.any { it.getVariance() == TypeVariance.OUT }
val thereIsIn = arguments.any { it.projectionKind == Variance.IN_VARIANCE } val thereIsIn = arguments.any { it.getVariance() == TypeVariance.IN }
if (thereIsOut) { if (thereIsOut) {
if (thereIsIn) { if (thereIsIn) {
// CS(Inv<out X>, Inv<in Y>) = Inv<*> // CS(Inv<out X>, Inv<in Y>) = Inv<*>
return StarProjectionImpl(parameter) return createStarProjection(parameter)
} else { } else {
asOut = true asOut = true
} }
@@ -230,16 +257,16 @@ object NewCommonSuperTypeCalculator {
// CS(Out<X>, Out<Y>) = Out<CS(X, Y)> // CS(Out<X>, Out<Y>) = Out<CS(X, Y)>
// CS(In<X>, In<Y>) = In<X & Y> // CS(In<X>, In<Y>) = In<X & Y>
if (asOut) { if (asOut) {
val type = commonSuperType(arguments.map { it.type.unwrap() }, depth + 1) val type = commonSuperType(arguments.map { it.getType() }, depth + 1)
return if (parameter.variance != Variance.INVARIANT) return type.asTypeProjection() else TypeProjectionImpl( return if (parameter.getVariance() != TypeVariance.INV) return type.asTypeArgument() else createTypeArgument(
Variance.OUT_VARIANCE, type,
type TypeVariance.OUT
) )
} else { } else {
val type = intersectTypes(arguments.map { it.type.unwrap() }) val type = intersectTypes(arguments.map { it.getType() })
return if (parameter.variance != Variance.INVARIANT) return type.asTypeProjection() else TypeProjectionImpl( return if (parameter.getVariance() != TypeVariance.INV) return type.asTypeArgument() else createTypeArgument(
Variance.IN_VARIANCE, type,
type TypeVariance.IN
) )
} }
} }
@@ -0,0 +1,19 @@
/*
* 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.resolve.calls.components
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
interface BuiltInsProvider {
val builtIns: KotlinBuiltIns
}
internal val ConstraintSystemBuilder.builtIns: KotlinBuiltIns get() = ((this as NewConstraintSystemImpl).typeSystemContext as BuiltInsProvider).builtIns
internal val NewConstraintSystem.builtIns: KotlinBuiltIns get() = ((this as NewConstraintSystemImpl).typeSystemContext as BuiltInsProvider).builtIns
@@ -0,0 +1,87 @@
/*
* 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.resolve.calls.components
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjector
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutorByConstructorMap
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
import org.jetbrains.kotlin.types.StubType
import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.TypeProjectionImpl
import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.checker.ClassicTypeSystemContext
import org.jetbrains.kotlin.types.checker.NewCapturedType
import org.jetbrains.kotlin.types.checker.NewCapturedTypeConstructor
import org.jetbrains.kotlin.types.model.*
import org.jetbrains.kotlin.utils.addToStdlib.cast
class ClassicTypeSystemContextForCS(override val builtIns: KotlinBuiltIns) : TypeSystemInferenceExtensionContextDelegate,
ClassicTypeSystemContext,
BuiltInsProvider {
override fun TypeVariableMarker.defaultType(): SimpleTypeMarker {
require(this is NewTypeVariable, this::errorMessage)
return this.defaultType
}
override fun TypeVariableMarker.freshTypeConstructor(): TypeConstructorMarker {
require(this is NewTypeVariable, this::errorMessage)
return this.freshTypeConstructor
}
override fun createCapturedType(
constructorProjection: TypeArgumentMarker,
constructorSupertypes: List<KotlinTypeMarker>,
lowerType: KotlinTypeMarker?,
captureStatus: CaptureStatus
): CapturedTypeMarker {
require(lowerType is UnwrappedType?, lowerType::errorMessage)
require(constructorProjection is TypeProjectionImpl, constructorProjection::errorMessage)
@Suppress("UNCHECKED_CAST")
val newCapturedTypeConstructor = NewCapturedTypeConstructor(
constructorProjection,
constructorSupertypes as List<UnwrappedType>
)
return NewCapturedType(
CaptureStatus.FOR_INCORPORATION,
newCapturedTypeConstructor,
lowerType = lowerType
)
}
override fun typeSubstitutorByTypeConstructor(map: Map<TypeConstructorMarker, KotlinTypeMarker>): TypeSubstitutorMarker {
return NewTypeSubstitutorByConstructorMap(map.cast())
}
override fun TypeSubstitutorMarker.safeSubstitute(type: KotlinTypeMarker): KotlinTypeMarker {
require(type is UnwrappedType, this::errorMessage)
require(this is NewTypeSubstitutor, this::errorMessage)
return this.safeSubstitute(type)
}
override fun createStubType(typeVariable: TypeVariableMarker): StubTypeMarker {
return StubType(typeVariable.freshTypeConstructor() as TypeConstructor, typeVariable.defaultType().isMarkedNullable())
}
}
@Suppress("NOTHING_TO_INLINE")
private inline fun Any?.errorMessage(): String {
return "ClassicTypeSystemContextForCS couldn't handle: $this, ${this?.let { it::class }}"
}
@Suppress("FunctionName")
fun NewConstraintSystemImpl(
constraintInjector: ConstraintInjector,
builtIns: KotlinBuiltIns
): NewConstraintSystemImpl {
return NewConstraintSystemImpl(constraintInjector, ClassicTypeSystemContextForCS(builtIns))
}
@@ -14,10 +14,10 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage.Empt
import org.jetbrains.kotlin.resolve.calls.inference.model.ExpectedTypeConstraintPosition import org.jetbrains.kotlin.resolve.calls.inference.model.ExpectedTypeConstraintPosition
import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.tower.forceResolution import org.jetbrains.kotlin.resolve.calls.tower.forceResolution
import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor
import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext
class KotlinCallCompleter( class KotlinCallCompleter(
private val postponedArgumentsAnalyzer: PostponedArgumentsAnalyzer, private val postponedArgumentsAnalyzer: PostponedArgumentsAnalyzer,
@@ -196,13 +196,16 @@ class KotlinCallCompleter(
private fun KotlinResolutionCandidate.hasProperNonTrivialLowerConstraints(typeVariable: UnwrappedType): Boolean { private fun KotlinResolutionCandidate.hasProperNonTrivialLowerConstraints(typeVariable: UnwrappedType): Boolean {
assert(csBuilder.isTypeVariable(typeVariable)) { "$typeVariable is not a type variable" } assert(csBuilder.isTypeVariable(typeVariable)) { "$typeVariable is not a type variable" }
val context = getSystem() as TypeSystemInferenceExtensionContext
val constructor = typeVariable.constructor val constructor = typeVariable.constructor
val variableWithConstraints = csBuilder.currentStorage().notFixedTypeVariables[constructor] ?: return false val variableWithConstraints = csBuilder.currentStorage().notFixedTypeVariables[constructor] ?: return false
val constraints = variableWithConstraints.constraints val constraints = variableWithConstraints.constraints
return constraints.isNotEmpty() && constraints.all { return constraints.isNotEmpty() && constraints.all {
!trivialConstraintTypeInferenceOracle.isTrivialConstraint(it) && it.type.constructor !is IntegerLiteralTypeConstructor && !trivialConstraintTypeInferenceOracle.isTrivialConstraint(it) &&
with(context) { !it.type.typeConstructor().isIntegerLiteralTypeConstructor() } &&
it.kind.isLower() && csBuilder.isProperType(it.type) it.kind.isLower() && csBuilder.isProperType(it.type)
} }
} }
private fun KotlinResolutionCandidate.computeReturnTypeWithSmartCastInfo( private fun KotlinResolutionCandidate.computeReturnTypeWithSmartCastInfo(
@@ -19,10 +19,13 @@ package org.jetbrains.kotlin.resolve.calls.components
import org.jetbrains.kotlin.builtins.* import org.jetbrains.kotlin.builtins.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem
import org.jetbrains.kotlin.resolve.calls.inference.model.ArgumentConstraintPosition import org.jetbrains.kotlin.resolve.calls.inference.model.ArgumentConstraintPosition
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
import org.jetbrains.kotlin.resolve.calls.inference.model.LHSArgumentConstraintPosition import org.jetbrains.kotlin.resolve.calls.inference.model.LHSArgumentConstraintPosition
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableForLambdaReturnType import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableForLambdaReturnType
import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.typeUtil.builtIns import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -141,7 +144,8 @@ private fun preprocessCallableReference(
if (expectedType == null) return result if (expectedType == null) return result
val notCallableTypeConstructor = val notCallableTypeConstructor =
csBuilder.getProperSuperTypeConstructors(expectedType).firstOrNull { !ReflectionTypes.isPossibleExpectedCallableType(it) } csBuilder.getProperSuperTypeConstructors(expectedType)
.firstOrNull { !ReflectionTypes.isPossibleExpectedCallableType(it.requireIs()) }
argument.lhsResult.safeAs<LHSResult.Type>()?.let { argument.lhsResult.safeAs<LHSResult.Type>()?.let {
val lhsType = it.unboundDetailedReceiver.stableType val lhsType = it.unboundDetailedReceiver.stableType
@@ -151,7 +155,13 @@ private fun preprocessCallableReference(
} }
} }
if (notCallableTypeConstructor != null) { if (notCallableTypeConstructor != null) {
diagnosticsHolder.addDiagnostic(NotCallableExpectedType(argument, expectedType, notCallableTypeConstructor)) diagnosticsHolder.addDiagnostic(
NotCallableExpectedType(
argument,
expectedType,
notCallableTypeConstructor.requireIs()
)
)
} }
return result return result
} }
@@ -163,3 +173,8 @@ private fun preprocessCollectionLiteralArgument(
// todo add some checks about expected type // todo add some checks about expected type
return ResolvedCollectionLiteralAtom(collectionLiteralArgument, expectedType) return ResolvedCollectionLiteralAtom(collectionLiteralArgument, expectedType)
} }
internal inline fun <reified T : Any> Any.requireIs(): T {
require(this is T)
return this
}
@@ -10,22 +10,22 @@ import org.jetbrains.kotlin.resolve.calls.inference.addSubsystemFromArgument
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.model.* import org.jetbrains.kotlin.resolve.calls.inference.model.*
import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.types.StubType
import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.model.*
import org.jetbrains.kotlin.types.typeUtil.builtIns import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.utils.addToStdlib.cast
class PostponedArgumentsAnalyzer( class PostponedArgumentsAnalyzer(
private val callableReferenceResolver: CallableReferenceResolver private val callableReferenceResolver: CallableReferenceResolver
) { ) {
interface Context { interface Context : TypeSystemInferenceExtensionContext {
fun buildCurrentSubstitutor(additionalBindings: Map<TypeConstructor, StubType>): NewTypeSubstitutor fun buildCurrentSubstitutor(additionalBindings: Map<TypeConstructorMarker, StubTypeMarker>): NewTypeSubstitutor
fun bindingStubsForPostponedVariables(): Map<NewTypeVariable, StubType> fun bindingStubsForPostponedVariables(): Map<TypeVariableMarker, StubTypeMarker>
// type can be proper if it not contains not fixed type variables // type can be proper if it not contains not fixed type variables
fun canBeProper(type: UnwrappedType): Boolean fun canBeProper(type: KotlinTypeMarker): Boolean
fun hasUpperOrEqualUnitConstraint(type: UnwrappedType): Boolean fun hasUpperOrEqualUnitConstraint(type: KotlinTypeMarker): Boolean
// mutable operations // mutable operations
fun addOtherSystem(otherSystem: ConstraintStorage) fun addOtherSystem(otherSystem: ConstraintStorage)
@@ -64,7 +64,7 @@ class PostponedArgumentsAnalyzer(
diagnosticHolder: KotlinDiagnosticsHolder diagnosticHolder: KotlinDiagnosticsHolder
) { ) {
val stubsForPostponedVariables = c.bindingStubsForPostponedVariables() val stubsForPostponedVariables = c.bindingStubsForPostponedVariables()
val currentSubstitutor = c.buildCurrentSubstitutor(stubsForPostponedVariables.mapKeys { it.key.freshTypeConstructor }) val currentSubstitutor = c.buildCurrentSubstitutor(stubsForPostponedVariables.mapKeys { it.key.freshTypeConstructor(c) })
fun substitute(type: UnwrappedType) = currentSubstitutor.safeSubstitute(type) fun substitute(type: UnwrappedType) = currentSubstitutor.safeSubstitute(type)
@@ -87,7 +87,7 @@ class PostponedArgumentsAnalyzer(
receiver, receiver,
parameters, parameters,
expectedTypeForReturnArguments, expectedTypeForReturnArguments,
stubsForPostponedVariables stubsForPostponedVariables.cast()
) )
returnArguments.forEach { c.addSubsystemFromArgument(it) } returnArguments.forEach { c.addSubsystemFromArgument(it) }
@@ -115,7 +115,7 @@ class PostponedArgumentsAnalyzer(
val variable = variableWithConstraints.typeVariable val variable = variableWithConstraints.typeVariable
c.getBuilder().unmarkPostponedVariable(variable) c.getBuilder().unmarkPostponedVariable(variable)
c.getBuilder().addEqualityConstraint(variable.defaultType, resultType, CoroutinePosition()) c.getBuilder().addEqualityConstraint(variable.defaultType(c), resultType, CoroutinePosition())
} }
} }
} }
@@ -24,27 +24,29 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.types.TypeConstructor import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
import org.jetbrains.kotlin.types.model.TypeVariableMarker
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
interface ConstraintSystemOperation { interface ConstraintSystemOperation {
val hasContradiction: Boolean val hasContradiction: Boolean
fun registerVariable(variable: NewTypeVariable) fun registerVariable(variable: TypeVariableMarker)
fun markPostponedVariable(variable: NewTypeVariable) fun markPostponedVariable(variable: TypeVariableMarker)
fun unmarkPostponedVariable(variable: NewTypeVariable) fun unmarkPostponedVariable(variable: TypeVariableMarker)
fun addSubtypeConstraint(lowerType: UnwrappedType, upperType: UnwrappedType, position: ConstraintPosition) fun addSubtypeConstraint(lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker, position: ConstraintPosition)
fun addEqualityConstraint(a: UnwrappedType, b: UnwrappedType, position: ConstraintPosition) fun addEqualityConstraint(a: KotlinTypeMarker, b: KotlinTypeMarker, position: ConstraintPosition)
fun isProperType(type: UnwrappedType): Boolean fun isProperType(type: KotlinTypeMarker): Boolean
fun isTypeVariable(type: UnwrappedType): Boolean fun isTypeVariable(type: KotlinTypeMarker): Boolean
fun isPostponedTypeVariable(typeVariable: NewTypeVariable): Boolean fun isPostponedTypeVariable(typeVariable: TypeVariableMarker): Boolean
fun getProperSuperTypeConstructors(type: UnwrappedType): List<TypeConstructor> fun getProperSuperTypeConstructors(type: KotlinTypeMarker): List<TypeConstructorMarker>
} }
interface ConstraintSystemBuilder : ConstraintSystemOperation { interface ConstraintSystemBuilder : ConstraintSystemOperation {
val builtIns: KotlinBuiltIns //val builtIns: KotlinBuiltIns
// if runOperations return true, then this operation will be applied, and function return true // if runOperations return true, then this operation will be applied, and function return true
fun runTransaction(runOperations: ConstraintSystemOperation.() -> Boolean): Boolean fun runTransaction(runOperations: ConstraintSystemOperation.() -> Boolean): Boolean
@@ -54,8 +56,8 @@ interface ConstraintSystemBuilder : ConstraintSystemOperation {
} }
fun ConstraintSystemBuilder.addSubtypeConstraintIfCompatible( fun ConstraintSystemBuilder.addSubtypeConstraintIfCompatible(
lowerType: UnwrappedType, lowerType: KotlinTypeMarker,
upperType: UnwrappedType, upperType: KotlinTypeMarker,
position: ConstraintPosition position: ConstraintPosition
) = ) =
runTransaction { runTransaction {
@@ -20,11 +20,15 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutorByConstructorMap import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutorByConstructorMap
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.model.StubTypeMarker
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
import org.jetbrains.kotlin.utils.addToStdlib.cast
fun ConstraintStorage.buildCurrentSubstitutor(additionalBindings: Map<TypeConstructor, StubType>): NewTypeSubstitutorByConstructorMap = fun ConstraintStorage.buildCurrentSubstitutor(additionalBindings: Map<TypeConstructorMarker, StubTypeMarker>): NewTypeSubstitutorByConstructorMap =
NewTypeSubstitutorByConstructorMap(fixedTypeVariables.entries.associate { it.key to it.value } + additionalBindings) NewTypeSubstitutorByConstructorMap( (fixedTypeVariables.entries.associate { it.key to it.value } + additionalBindings).cast() ) // TODO: SUB
fun ConstraintStorage.buildResultingSubstitutor(): NewTypeSubstitutor { fun ConstraintStorage.buildResultingSubstitutor(): NewTypeSubstitutor {
val currentSubstitutorMap = fixedTypeVariables.entries.associate { val currentSubstitutorMap = fixedTypeVariables.entries.associate {
@@ -33,11 +37,11 @@ fun ConstraintStorage.buildResultingSubstitutor(): NewTypeSubstitutor {
val uninferredSubstitutorMap = notFixedTypeVariables.entries.associate { (freshTypeConstructor, typeVariable) -> val uninferredSubstitutorMap = notFixedTypeVariables.entries.associate { (freshTypeConstructor, typeVariable) ->
freshTypeConstructor to ErrorUtils.createErrorTypeWithCustomConstructor( freshTypeConstructor to ErrorUtils.createErrorTypeWithCustomConstructor(
"Uninferred type", "Uninferred type",
typeVariable.typeVariable.freshTypeConstructor (typeVariable.typeVariable as NewTypeVariable).freshTypeConstructor// TODO: SUB
) )
} }
return NewTypeSubstitutorByConstructorMap(currentSubstitutorMap + uninferredSubstitutorMap) return NewTypeSubstitutorByConstructorMap((currentSubstitutorMap + uninferredSubstitutorMap).cast()) // TODO: SUB
} }
val CallableDescriptor.returnTypeOrNothing: UnwrappedType val CallableDescriptor.returnTypeOrNothing: UnwrappedType
@@ -63,7 +67,7 @@ fun CallableDescriptor.substituteAndApproximateCapturedTypes(substitutor: NewTyp
override fun prepareTopLevelType(topLevelType: KotlinType, position: Variance) = override fun prepareTopLevelType(topLevelType: KotlinType, position: Variance) =
substitutor.safeSubstitute(topLevelType.unwrap()).let { substitutedType -> substitutor.safeSubstitute(topLevelType.unwrap()).let { substitutedType ->
TypeApproximator().approximateToSuperType(substitutedType, TypeApproximatorConfiguration.CapturedAndIntegerLiteralsTypesApproximation) TypeApproximator(builtIns).approximateToSuperType(substitutedType, TypeApproximatorConfiguration.CapturedAndIntegerLiteralsTypesApproximation)
?: substitutedType ?: substitutedType
} }
} }
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
interface NewConstraintSystem { interface NewConstraintSystem {
val builtIns: KotlinBuiltIns // val builtIns: KotlinBuiltIns
val hasContradiction: Boolean val hasContradiction: Boolean
val diagnostics: List<KotlinCallDiagnostic> val diagnostics: List<KotlinCallDiagnostic>
@@ -5,34 +5,28 @@
package org.jetbrains.kotlin.resolve.calls.inference.components package org.jetbrains.kotlin.resolve.calls.inference.components
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.types.AbstractNullabilityChecker
import org.jetbrains.kotlin.resolve.descriptorUtil.hasExactAnnotation import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.resolve.descriptorUtil.hasNoInferAnnotation import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.KotlinTypeFactory.flexibleType
import org.jetbrains.kotlin.types.checker.* import org.jetbrains.kotlin.types.checker.*
import org.jetbrains.kotlin.types.model.CapturedTypeMarker import org.jetbrains.kotlin.types.model.*
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.types.typeUtil.contains
abstract class TypeCheckerContextForConstraintSystem : ClassicTypeCheckerContext(errorTypeEqualsToAnything = true, allowedTypeVariable = false) { abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheckerContext(), TypeSystemInferenceExtensionContext {
abstract fun isMyTypeVariable(type: SimpleType): Boolean override val KotlinTypeMarker.isAllowedTypeVariable: Boolean
get() = false
override val isErrorTypeEqualsToAnything: Boolean
get() = true
abstract fun isMyTypeVariable(type: SimpleTypeMarker): Boolean
// super and sub type isSingleClassifierType // super and sub type isSingleClassifierType
abstract fun addUpperConstraint(typeVariable: TypeConstructor, superType: UnwrappedType) abstract fun addUpperConstraint(typeVariable: TypeConstructorMarker, superType: KotlinTypeMarker)
abstract fun addLowerConstraint(typeVariable: TypeConstructor, subType: UnwrappedType) abstract fun addLowerConstraint(typeVariable: TypeConstructorMarker, subType: KotlinTypeMarker)
override fun getLowerCapturedTypePolicy(subType: SimpleTypeMarker, superType: CapturedTypeMarker): LowerCapturedTypePolicy { override fun getLowerCapturedTypePolicy(subType: SimpleTypeMarker, superType: CapturedTypeMarker): LowerCapturedTypePolicy = when {
require(subType is SimpleType)
require(superType is NewCapturedType)
return getLowerCapturedTypePolicy(subType, superType)
}
private fun getLowerCapturedTypePolicy(subType: SimpleType, superType: NewCapturedType) = when {
isMyTypeVariable(subType) -> LowerCapturedTypePolicy.SKIP_LOWER isMyTypeVariable(subType) -> LowerCapturedTypePolicy.SKIP_LOWER
subType.contains { it.anyBound(this::isMyTypeVariable) } -> LowerCapturedTypePolicy.CHECK_ONLY_LOWER subType.contains { it.anyBound(this::isMyTypeVariable) } -> LowerCapturedTypePolicy.CHECK_ONLY_LOWER
else -> LowerCapturedTypePolicy.CHECK_SUBTYPE_AND_LOWER else -> LowerCapturedTypePolicy.CHECK_SUBTYPE_AND_LOWER
@@ -45,16 +39,14 @@ abstract class TypeCheckerContextForConstraintSystem : ClassicTypeCheckerContext
* override val sameConstructorPolicy get() = SeveralSupertypesWithSameConstructorPolicy.TAKE_FIRST_FOR_SUBTYPING * override val sameConstructorPolicy get() = SeveralSupertypesWithSameConstructorPolicy.TAKE_FIRST_FOR_SUBTYPING
*/ */
final override fun addSubtypeConstraint(subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean? { final override fun addSubtypeConstraint(subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean? {
require(subType is UnwrappedType)
require(superType is UnwrappedType)
val hasNoInfer = subType.isTypeVariableWithNoInfer() || superType.isTypeVariableWithNoInfer() val hasNoInfer = subType.isTypeVariableWithNoInfer() || superType.isTypeVariableWithNoInfer()
if (hasNoInfer) return true if (hasNoInfer) return true
val hasExact = subType.isTypeVariableWithExact() || superType.isTypeVariableWithExact() val hasExact = subType.isTypeVariableWithExact() || superType.isTypeVariableWithExact()
// we should strip annotation's because we have incorporation operation and they should be not affected // we should strip annotation's because we have incorporation operation and they should be not affected
val mySubType = if (hasExact) subType.replaceAnnotations(Annotations.EMPTY) else subType val mySubType = if (hasExact) subType.removeAnnotations() else subType
val mySuperType = if (hasExact) superType.replaceAnnotations(Annotations.EMPTY) else superType val mySuperType = if (hasExact) superType.removeAnnotations() else superType
val result = internalAddSubtypeConstraint(mySubType, mySuperType) val result = internalAddSubtypeConstraint(mySubType, mySuperType)
if (!hasExact) return result if (!hasExact) return result
@@ -65,13 +57,13 @@ abstract class TypeCheckerContextForConstraintSystem : ClassicTypeCheckerContext
return (result ?: true) && (result2 ?: true) return (result ?: true) && (result2 ?: true)
} }
private fun UnwrappedType.isTypeVariableWithExact() = private fun KotlinTypeMarker.isTypeVariableWithExact() =
anyBound(this@TypeCheckerContextForConstraintSystem::isMyTypeVariable) && hasExactAnnotation() anyBound(this@AbstractTypeCheckerContextForConstraintSystem::isMyTypeVariable) && hasExactAnnotation()
private fun UnwrappedType.isTypeVariableWithNoInfer() = private fun KotlinTypeMarker.isTypeVariableWithNoInfer() =
anyBound(this@TypeCheckerContextForConstraintSystem::isMyTypeVariable) && hasNoInferAnnotation() anyBound(this@AbstractTypeCheckerContextForConstraintSystem::isMyTypeVariable) && hasNoInferAnnotation()
private fun internalAddSubtypeConstraint(subType: UnwrappedType, superType: UnwrappedType): Boolean? { private fun internalAddSubtypeConstraint(subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean? {
assertInputTypes(subType, superType) assertInputTypes(subType, superType)
var answer: Boolean? = null var answer: Boolean? = null
@@ -92,12 +84,13 @@ abstract class TypeCheckerContextForConstraintSystem : ClassicTypeCheckerContext
} }
// extract type variable only from type like Captured(out T) // extract type variable only from type like Captured(out T)
private fun extractTypeVariableForSubtype(type: UnwrappedType): UnwrappedType? { private fun extractTypeVariableForSubtype(type: KotlinTypeMarker): KotlinTypeMarker? {
if (type !is NewCapturedType) return null
val projection = type.constructor.projection val type = type.asSimpleType()?.asCapturedType() ?: return null
return if (projection.projectionKind == Variance.OUT_VARIANCE)
projection.type.takeIf { it is SimpleType && isMyTypeVariable(it) }?.unwrap() val projection = type.typeConstructorProjection()
return if (projection.getVariance() == TypeVariance.OUT)
projection.getType().takeIf { it is SimpleTypeMarker && isMyTypeVariable(it) }?.asSimpleType()
else else
null null
} }
@@ -139,35 +132,38 @@ abstract class TypeCheckerContextForConstraintSystem : ClassicTypeCheckerContext
* *
* => (Foo..Bar) <: T! -- (Foo!! .. Bar) <: T * => (Foo..Bar) <: T! -- (Foo!! .. Bar) <: T
*/ */
private fun simplifyLowerConstraint(typeVariable: UnwrappedType, subType: UnwrappedType): Boolean { private fun simplifyLowerConstraint(typeVariable: KotlinTypeMarker, subType: KotlinTypeMarker): Boolean {
val lowerConstraint = when (typeVariable) { val lowerConstraint = when (typeVariable) {
is SimpleType -> is SimpleTypeMarker ->
// Foo <: T or // Foo <: T or
// Foo <: T? -- Foo!! <: T // Foo <: T? -- Foo!! <: T
if (typeVariable.isMarkedNullable) subType.makeDefinitelyNotNullOrNotNull() else subType if (typeVariable.isMarkedNullable()) subType.makeDefinitelyNotNullOrNotNull() else subType
is FlexibleType -> { is FlexibleTypeMarker -> {
assertFlexibleTypeVariable(typeVariable) assertFlexibleTypeVariable(typeVariable)
when (subType) { when (subType) {
is SimpleType -> is SimpleTypeMarker ->
// Foo <: T! -- (Foo!! .. Foo) <: T // Foo <: T! -- (Foo!! .. Foo) <: T
flexibleType(subType.makeSimpleTypeDefinitelyNotNullOrNotNull(), subType) createFlexibleType(subType.makeSimpleTypeDefinitelyNotNullOrNotNull(), subType)
is FlexibleType -> is FlexibleTypeMarker ->
// (Foo..Bar) <: T! -- (Foo!! .. Bar) <: T // (Foo..Bar) <: T! -- (Foo!! .. Bar) <: T
flexibleType(subType.lowerBound.makeSimpleTypeDefinitelyNotNullOrNotNull(), subType.upperBound) createFlexibleType(subType.lowerBound().makeSimpleTypeDefinitelyNotNullOrNotNull(), subType.upperBound())
else -> error("sealed")
} }
} }
else -> error("sealed")
} }
addLowerConstraint(typeVariable.constructor, lowerConstraint) addLowerConstraint(typeVariable.typeConstructor(), lowerConstraint)
return true return true
} }
private fun assertFlexibleTypeVariable(typeVariable: FlexibleType) { private fun assertFlexibleTypeVariable(typeVariable: FlexibleTypeMarker) {
assert(typeVariable.lowerBound.constructor == typeVariable.upperBound.constructor) { assert(typeVariable.lowerBound().typeConstructor() == typeVariable.upperBound().typeConstructor()) {
"Flexible type variable ($typeVariable) should have bounds with the same type constructor, i.e. (T..T?)" "Flexible type variable ($typeVariable) should have bounds with the same type constructor, i.e. (T..T?)"
} }
} }
@@ -177,40 +173,46 @@ abstract class TypeCheckerContextForConstraintSystem : ClassicTypeCheckerContext
* T? <: Foo <=> T <: Foo && Nothing? <: Foo * T? <: Foo <=> T <: Foo && Nothing? <: Foo
* T <: Foo -- leave as is * T <: Foo -- leave as is
*/ */
private fun simplifyUpperConstraint(typeVariable: UnwrappedType, superType: UnwrappedType): Boolean { private fun simplifyUpperConstraint(typeVariable: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean {
@Suppress("NAME_SHADOWING") @Suppress("NAME_SHADOWING")
val typeVariable = typeVariable.lowerIfFlexible() val typeVariable = typeVariable.lowerBoundIfFlexible()
@Suppress("NAME_SHADOWING") @Suppress("NAME_SHADOWING")
val superType = if (typeVariable is DefinitelyNotNullType) superType.makeNullableAsSpecified(true) else superType val superType = if (typeVariable.isDefinitelyNotNullType()) superType.withNullability(true) else superType
addUpperConstraint(typeVariable.constructor, superType) addUpperConstraint(typeVariable.typeConstructor(), superType)
if (typeVariable.isMarkedNullable) { if (typeVariable.isMarkedNullable()) {
// here is important that superType is singleClassifierType // here is important that superType is singleClassifierType
return superType.anyBound(this::isMyTypeVariable) || return superType.anyBound(this::isMyTypeVariable) ||
isSubtypeOfByTypeChecker(typeVariable.builtIns.nullableNothingType, superType) isSubtypeOfByTypeChecker(nullableNothingType(), superType)
} }
return true return true
} }
private fun simplifyConstraintForPossibleIntersectionSubType(subType: UnwrappedType, superType: UnwrappedType): Boolean? { private fun simplifyConstraintForPossibleIntersectionSubType(subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean? {
@Suppress("NAME_SHADOWING") @Suppress("NAME_SHADOWING")
val subType = subType.lowerIfFlexible() val subType = subType.lowerBoundIfFlexible()
if (!subType.isIntersectionType) return null if (!subType.typeConstructor().isIntersection()) return null
assert(!subType.isMarkedNullable) { "Intersection type should not be marked nullable!: $subType" } assert(!subType.isMarkedNullable()) { "Intersection type should not be marked nullable!: $subType" }
// TODO: may be we lose flexibility here // TODO: may be we lose flexibility here
val subIntersectionTypes = (subType.constructor as IntersectionTypeConstructor).supertypes.map { it.lowerIfFlexible() } val subIntersectionTypes = (subType.typeConstructor().supertypes()).map { it.lowerBoundIfFlexible() }
val typeVariables = subIntersectionTypes.filter(this::isMyTypeVariable).takeIf { it.isNotEmpty() } ?: return null val typeVariables = subIntersectionTypes.filter(this::isMyTypeVariable).takeIf { it.isNotEmpty() } ?: return null
val notTypeVariables = subIntersectionTypes.filterNot(this::isMyTypeVariable) val notTypeVariables = subIntersectionTypes.filterNot(this::isMyTypeVariable)
// todo: may be we can do better then that. // todo: may be we can do better then that.
if (notTypeVariables.isNotEmpty() && NewKotlinTypeChecker.isSubtypeOf(intersectTypes(notTypeVariables) as KotlinType, superType)) { if (notTypeVariables.isNotEmpty() &&
AbstractTypeChecker.isSubtypeOf(
this as TypeCheckerProviderContext,
intersectTypes(notTypeVariables),
superType
)
) {
return true return true
} }
@@ -229,22 +231,22 @@ abstract class TypeCheckerContextForConstraintSystem : ClassicTypeCheckerContext
// here we try to add constraint {Any & T} <: S from `id(a)` // here we try to add constraint {Any & T} <: S from `id(a)`
// Previously we thought that if `Any` isn't a subtype of S => T <: S, which is wrong, now we use weaker upper constraint // Previously we thought that if `Any` isn't a subtype of S => T <: S, which is wrong, now we use weaker upper constraint
// TODO: rethink, maybe we should take nullability into account somewhere else // TODO: rethink, maybe we should take nullability into account somewhere else
if (notTypeVariables.any { NullabilityChecker.isSubtypeOfAny(it) }) { if (notTypeVariables.any { AbstractNullabilityChecker.isSubtypeOfAny(this as TypeCheckerProviderContext, it) }) {
return typeVariables.all { simplifyUpperConstraint(it, superType.makeNullableAsSpecified(true)) } return typeVariables.all { simplifyUpperConstraint(it, superType.withNullability(true)) }
} }
return typeVariables.all { simplifyUpperConstraint(it, superType) } return typeVariables.all { simplifyUpperConstraint(it, superType) }
} }
private fun isSubtypeOfByTypeChecker(subType: UnwrappedType, superType: UnwrappedType) = private fun isSubtypeOfByTypeChecker(subType: KotlinTypeMarker, superType: KotlinTypeMarker) =
with(NewKotlinTypeChecker) { this@TypeCheckerContextForConstraintSystem.isSubtypeOf(subType, superType) } AbstractTypeChecker.isSubtypeOf(this as AbstractTypeCheckerContext, subType, superType)
private fun assertInputTypes(subType: UnwrappedType, superType: UnwrappedType) { private fun assertInputTypes(subType: KotlinTypeMarker, superType: KotlinTypeMarker) {
fun correctSubType(subType: SimpleType) = fun correctSubType(subType: SimpleTypeMarker) =
subType.isSingleClassifierType || subType.isIntersectionType || isMyTypeVariable(subType) || subType.isError || subType.isIntegerLiteralType subType.isSingleClassifierType() || subType.typeConstructor().isIntersection() || isMyTypeVariable(subType) || subType.isError() || subType.isIntegerLiteralType()
fun correctSuperType(superType: SimpleType) = fun correctSuperType(superType: SimpleTypeMarker) =
superType.isSingleClassifierType || superType.isIntersectionType || isMyTypeVariable(superType) || superType.isError || superType.isIntegerLiteralType superType.isSingleClassifierType() || superType.typeConstructor().isIntersection() || isMyTypeVariable(superType) || superType.isError() || superType.isIntegerLiteralType()
assert(subType.bothBounds(::correctSubType)) { assert(subType.bothBounds(::correctSubType)) {
"Not singleClassifierType and not intersection subType: $subType" "Not singleClassifierType and not intersection subType: $subType"
@@ -254,13 +256,15 @@ abstract class TypeCheckerContextForConstraintSystem : ClassicTypeCheckerContext
} }
} }
private inline fun UnwrappedType.bothBounds(f: (SimpleType) -> Boolean) = when (this) { private inline fun KotlinTypeMarker.bothBounds(f: (SimpleTypeMarker) -> Boolean) = when (this) {
is SimpleType -> f(this) is SimpleTypeMarker -> f(this)
is FlexibleType -> f(lowerBound) && f(upperBound) is FlexibleTypeMarker -> f(lowerBound()) && f(upperBound())
else -> error("sealed")
} }
private inline fun UnwrappedType.anyBound(f: (SimpleType) -> Boolean) = when (this) { private inline fun KotlinTypeMarker.anyBound(f: (SimpleTypeMarker) -> Boolean) = when (this) {
is SimpleType -> f(this) is SimpleTypeMarker -> f(this)
is FlexibleType -> f(lowerBound) || f(upperBound) is FlexibleTypeMarker -> f(lowerBound()) || f(upperBound())
else -> error("sealed")
} }
} }
@@ -7,13 +7,9 @@ package org.jetbrains.kotlin.resolve.calls.inference.components
import org.jetbrains.kotlin.resolve.calls.inference.model.Constraint import org.jetbrains.kotlin.resolve.calls.inference.model.Constraint
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraints import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraints
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.NewCapturedType import org.jetbrains.kotlin.types.model.*
import org.jetbrains.kotlin.types.checker.NewCapturedTypeConstructor
import org.jetbrains.kotlin.types.model.CaptureStatus
import org.jetbrains.kotlin.types.typeUtil.contains
import org.jetbrains.kotlin.utils.SmartSet import org.jetbrains.kotlin.utils.SmartSet
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
import java.util.* import java.util.*
@@ -24,130 +20,161 @@ class ConstraintIncorporator(
val trivialConstraintTypeInferenceOracle: TrivialConstraintTypeInferenceOracle val trivialConstraintTypeInferenceOracle: TrivialConstraintTypeInferenceOracle
) { ) {
interface Context { interface Context : TypeSystemInferenceExtensionContext {
val allTypeVariablesWithConstraints: Collection<VariableWithConstraints> val allTypeVariablesWithConstraints: Collection<VariableWithConstraints>
// if such type variable is fixed then it is error // if such type variable is fixed then it is error
fun getTypeVariable(typeConstructor: TypeConstructor): NewTypeVariable? fun getTypeVariable(typeConstructor: TypeConstructorMarker): TypeVariableMarker?
fun getConstraintsForVariable(typeVariable: NewTypeVariable): Collection<Constraint> fun getConstraintsForVariable(typeVariable: TypeVariableMarker): Collection<Constraint>
fun addNewIncorporatedConstraint(lowerType: UnwrappedType, upperType: UnwrappedType) fun addNewIncorporatedConstraint(lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker)
} }
// \alpha is typeVariable, \beta -- other type variable registered in ConstraintStorage // \alpha is typeVariable, \beta -- other type variable registered in ConstraintStorage
fun incorporate(c: Context, typeVariable: NewTypeVariable, constraint: Constraint) { fun incorporate(c: Context, typeVariable: TypeVariableMarker, constraint: Constraint) {
// we shouldn't incorporate recursive constraint -- It is too dangerous // we shouldn't incorporate recursive constraint -- It is too dangerous
if (constraint.type.contains { it.constructor == typeVariable.freshTypeConstructor }) return with(c) {
if (constraint.type.contains { it.typeConstructor() == typeVariable.freshTypeConstructor() }) return
}
directWithVariable(c, typeVariable, constraint) c.directWithVariable(typeVariable, constraint)
otherInsideMyConstraint(c, typeVariable, constraint) c.otherInsideMyConstraint(typeVariable, constraint)
insideOtherConstraint(c, typeVariable, constraint) c.insideOtherConstraint(typeVariable, constraint)
} }
// A <:(=) \alpha <:(=) B => A <: B // A <:(=) \alpha <:(=) B => A <: B
private fun directWithVariable(c: Context, typeVariable: NewTypeVariable, constraint: Constraint) { private fun Context.directWithVariable(
typeVariable: TypeVariableMarker,
constraint: Constraint
) {
// \alpha <: constraint.type // \alpha <: constraint.type
if (constraint.kind != ConstraintKind.LOWER) { if (constraint.kind != ConstraintKind.LOWER) {
c.getConstraintsForVariable(typeVariable).forEach { getConstraintsForVariable(typeVariable).forEach {
if (it.kind != ConstraintKind.UPPER) { if (it.kind != ConstraintKind.UPPER) {
c.addNewIncorporatedConstraint(it.type, constraint.type) addNewIncorporatedConstraint(it.type, constraint.type)
} }
} }
} }
// constraint.type <: \alpha // constraint.type <: \alpha
if (constraint.kind != ConstraintKind.UPPER) { if (constraint.kind != ConstraintKind.UPPER) {
c.getConstraintsForVariable(typeVariable).forEach { getConstraintsForVariable(typeVariable).forEach {
if (it.kind != ConstraintKind.LOWER) { if (it.kind != ConstraintKind.LOWER) {
c.addNewIncorporatedConstraint(constraint.type, it.type) addNewIncorporatedConstraint(constraint.type, it.type)
} }
} }
} }
} }
// \alpha <: Inv<\beta>, \beta <: Number => \alpha <: Inv<out Number> // \alpha <: Inv<\beta>, \beta <: Number => \alpha <: Inv<out Number>
private fun otherInsideMyConstraint(c: Context, typeVariable: NewTypeVariable, constraint: Constraint) { private fun Context.otherInsideMyConstraint(
val otherInMyConstraint = SmartSet.create<NewTypeVariable>() typeVariable: TypeVariableMarker,
constraint: Constraint
) {
val otherInMyConstraint = SmartSet.create<TypeVariableMarker>()
constraint.type.contains { constraint.type.contains {
otherInMyConstraint.addIfNotNull(c.getTypeVariable(it.constructor)) otherInMyConstraint.addIfNotNull(this.getTypeVariable(it.typeConstructor()))
false false
} }
for (otherTypeVariable in otherInMyConstraint) { for (otherTypeVariable in otherInMyConstraint) {
// to avoid ConcurrentModificationException // to avoid ConcurrentModificationException
val otherConstraints = ArrayList(c.getConstraintsForVariable(otherTypeVariable)) val otherConstraints = ArrayList(this.getConstraintsForVariable(otherTypeVariable))
for (otherConstraint in otherConstraints) { for (otherConstraint in otherConstraints) {
generateNewConstraint(c, typeVariable, constraint, otherTypeVariable, otherConstraint) generateNewConstraint(typeVariable, constraint, otherTypeVariable, otherConstraint)
} }
} }
} }
// \alpha <: Number, \beta <: Inv<\alpha> => \beta <: Inv<out Number> // \alpha <: Number, \beta <: Inv<\alpha> => \beta <: Inv<out Number>
private fun insideOtherConstraint(c: Context, typeVariable: NewTypeVariable, constraint: Constraint) { private fun Context.insideOtherConstraint(
for (typeVariableWithConstraint in c.allTypeVariablesWithConstraints) { typeVariable: TypeVariableMarker,
constraint: Constraint
) {
for (typeVariableWithConstraint in this@insideOtherConstraint.allTypeVariablesWithConstraints) {
val constraintsWhichConstraintMyVariable = typeVariableWithConstraint.constraints.filter { val constraintsWhichConstraintMyVariable = typeVariableWithConstraint.constraints.filter {
it.type.contains { it.constructor == typeVariable.freshTypeConstructor } it.type.contains { it.typeConstructor() == typeVariable.freshTypeConstructor() }
} }
constraintsWhichConstraintMyVariable.forEach { constraintsWhichConstraintMyVariable.forEach {
generateNewConstraint(c, typeVariableWithConstraint.typeVariable, it, typeVariable, constraint) generateNewConstraint(typeVariableWithConstraint.typeVariable, it, typeVariable, constraint)
} }
} }
} }
private fun generateNewConstraint( private fun Context.generateNewConstraint(
c: Context, targetVariable: TypeVariableMarker,
targetVariable: NewTypeVariable,
baseConstraint: Constraint, baseConstraint: Constraint,
otherVariable: NewTypeVariable, otherVariable: TypeVariableMarker,
otherConstraint: Constraint otherConstraint: Constraint
) { ) {
val baseConstraintType = baseConstraint.type val baseConstraintType = baseConstraint.type
val typeForApproximation = when (otherConstraint.kind) { val typeForApproximation = when (otherConstraint.kind) {
ConstraintKind.EQUALITY -> { ConstraintKind.EQUALITY -> {
baseConstraintType.substituteTypeVariable(otherVariable, otherConstraint.type) baseConstraintType.substitute(this, otherVariable, otherConstraint.type)
} }
ConstraintKind.UPPER -> { ConstraintKind.UPPER -> {
val newCapturedTypeConstructor = NewCapturedTypeConstructor( val temporaryCapturedType = createCapturedType(
TypeProjectionImpl(Variance.OUT_VARIANCE, otherConstraint.type), createTypeArgument(otherConstraint.type, TypeVariance.OUT),
listOf(otherConstraint.type) listOf(otherConstraint.type),
null,
CaptureStatus.FOR_INCORPORATION
) )
val temporaryCapturedType = NewCapturedType( // val newCapturedTypeConstructor = NewCapturedTypeConstructor(
CaptureStatus.FOR_INCORPORATION, // TypeProjectionImpl(Variance.OUT_VARIANCE, otherConstraint.type),
newCapturedTypeConstructor, // listOf(otherConstraint.type)
lowerType = null // )
) // val temporaryCapturedType = NewCapturedType(
baseConstraintType.substituteTypeVariable(otherVariable, temporaryCapturedType) // CaptureStatus.FOR_INCORPORATION,
// newCapturedTypeConstructor,
// lowerType = null
// )
baseConstraintType.substitute(this, otherVariable, temporaryCapturedType)
} }
ConstraintKind.LOWER -> { ConstraintKind.LOWER -> {
val newCapturedTypeConstructor = NewCapturedTypeConstructor( val temporaryCapturedType = createCapturedType(
TypeProjectionImpl(Variance.IN_VARIANCE, otherConstraint.type), createTypeArgument(otherConstraint.type, TypeVariance.IN),
emptyList() emptyList(),
otherConstraint.type,
CaptureStatus.FOR_INCORPORATION
) )
val temporaryCapturedType = NewCapturedType(
CaptureStatus.FOR_INCORPORATION, // val newCapturedTypeConstructor = NewCapturedTypeConstructor(
newCapturedTypeConstructor, // TypeProjectionImpl(Variance.IN_VARIANCE, otherConstraint.type),
lowerType = otherConstraint.type // emptyList()
) // )
baseConstraintType.substituteTypeVariable(otherVariable, temporaryCapturedType) // val temporaryCapturedType = NewCapturedType(
// CaptureStatus.FOR_INCORPORATION,
// newCapturedTypeConstructor,
// lowerType = otherConstraint.type
// )
baseConstraintType.substitute(this, otherVariable, temporaryCapturedType)
} }
} }
if (baseConstraint.kind != ConstraintKind.UPPER) { if (baseConstraint.kind != ConstraintKind.UPPER) {
val generatedConstraintType = approximateCapturedTypes(typeForApproximation, toSuper = false) val generatedConstraintType = approximateCapturedTypes(typeForApproximation, toSuper = false)
if (!trivialConstraintTypeInferenceOracle.isGeneratedConstraintTrivial(otherConstraint, generatedConstraintType)) { if (!trivialConstraintTypeInferenceOracle.isGeneratedConstraintTrivial(otherConstraint, generatedConstraintType)) {
c.addNewIncorporatedConstraint(generatedConstraintType, targetVariable.defaultType) addNewIncorporatedConstraint(generatedConstraintType, targetVariable.defaultType())
} }
} }
if (baseConstraint.kind != ConstraintKind.LOWER) { if (baseConstraint.kind != ConstraintKind.LOWER) {
val generatedConstraintType = approximateCapturedTypes(typeForApproximation, toSuper = true) val generatedConstraintType = approximateCapturedTypes(typeForApproximation, toSuper = true)
if (!trivialConstraintTypeInferenceOracle.isGeneratedConstraintTrivial(otherConstraint, generatedConstraintType)) { if (!trivialConstraintTypeInferenceOracle.isGeneratedConstraintTrivial(otherConstraint, generatedConstraintType)) {
c.addNewIncorporatedConstraint(targetVariable.defaultType, generatedConstraintType) addNewIncorporatedConstraint(targetVariable.defaultType(), generatedConstraintType)
} }
} }
} }
private fun approximateCapturedTypes(type: UnwrappedType, toSuper: Boolean): UnwrappedType = private fun KotlinTypeMarker.substitute(c: Context, typeVariable: TypeVariableMarker, value: KotlinTypeMarker): KotlinTypeMarker {
val substitutor = c.typeSubstitutorByTypeConstructor(mapOf(typeVariable.freshTypeConstructor(c) to value))
return substitutor.safeSubstitute(c, this)
}
private fun approximateCapturedTypes(type: KotlinTypeMarker, toSuper: Boolean): KotlinTypeMarker =
if (toSuper) typeApproximator.approximateToSuperType(type, TypeApproximatorConfiguration.IncorporationConfiguration) ?: type if (toSuper) typeApproximator.approximateToSuperType(type, TypeApproximatorConfiguration.IncorporationConfiguration) ?: type
else typeApproximator.approximateToSubType(type, TypeApproximatorConfiguration.IncorporationConfiguration) ?: type else typeApproximator.approximateToSubType(type, TypeApproximatorConfiguration.IncorporationConfiguration) ?: type
} }
@@ -16,35 +16,31 @@
package org.jetbrains.kotlin.resolve.calls.inference.components package org.jetbrains.kotlin.resolve.calls.inference.components
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.resolve.calls.inference.model.* import org.jetbrains.kotlin.resolve.calls.inference.model.*
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind.LOWER import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind.LOWER
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind.UPPER import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind.UPPER
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.NewCapturedType import org.jetbrains.kotlin.types.checker.NewCapturedType
import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker import org.jetbrains.kotlin.types.model.*
import org.jetbrains.kotlin.types.model.CaptureStatus
import org.jetbrains.kotlin.types.typeUtil.contains
import org.jetbrains.kotlin.types.typeUtil.isNothing
import org.jetbrains.kotlin.types.typeUtil.isNullableAny
import java.util.* import java.util.*
class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val typeApproximator: TypeApproximator) { class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val typeApproximator: TypeApproximator) {
private val ALLOWED_DEPTH_DELTA_FOR_INCORPORATION = 1 private val ALLOWED_DEPTH_DELTA_FOR_INCORPORATION = 1
interface Context { interface Context : TypeSystemInferenceExtensionContext {
val allTypeVariables: Map<TypeConstructor, NewTypeVariable> val allTypeVariables: Map<TypeConstructorMarker, TypeVariableMarker>
var maxTypeDepthFromInitialConstraints: Int var maxTypeDepthFromInitialConstraints: Int
val notFixedTypeVariables: MutableMap<TypeConstructor, MutableVariableWithConstraints> val notFixedTypeVariables: MutableMap<TypeConstructorMarker, MutableVariableWithConstraints>
val fixedTypeVariables: MutableMap<TypeConstructor, UnwrappedType> val fixedTypeVariables: MutableMap<TypeConstructorMarker, KotlinTypeMarker>
fun addInitialConstraint(initialConstraint: InitialConstraint) fun addInitialConstraint(initialConstraint: InitialConstraint)
fun addError(error: KotlinCallDiagnostic) fun addError(error: KotlinCallDiagnostic)
} }
fun addInitialSubtypeConstraint(c: Context, lowerType: UnwrappedType, upperType: UnwrappedType, position: ConstraintPosition) { fun addInitialSubtypeConstraint(c: Context, lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker, position: ConstraintPosition) {
val initialConstraint = InitialConstraint(lowerType, upperType, UPPER, position) val initialConstraint = InitialConstraint(lowerType, upperType, UPPER, position)
val incorporationPosition = IncorporationConstraintPosition(position, initialConstraint) val incorporationPosition = IncorporationConstraintPosition(position, initialConstraint)
c.addInitialConstraint(initialConstraint) c.addInitialConstraint(initialConstraint)
@@ -53,7 +49,7 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
addSubTypeConstraintAndIncorporateIt(c, lowerType, upperType, incorporationPosition) addSubTypeConstraintAndIncorporateIt(c, lowerType, upperType, incorporationPosition)
} }
fun addInitialEqualityConstraint(c: Context, a: UnwrappedType, b: UnwrappedType, position: ConstraintPosition) { fun addInitialEqualityConstraint(c: Context, a: KotlinTypeMarker, b: KotlinTypeMarker, position: ConstraintPosition) {
val initialConstraint = InitialConstraint(a, b, ConstraintKind.EQUALITY, position) val initialConstraint = InitialConstraint(a, b, ConstraintKind.EQUALITY, position)
val incorporationPosition = IncorporationConstraintPosition(position, initialConstraint) val incorporationPosition = IncorporationConstraintPosition(position, initialConstraint)
c.addInitialConstraint(initialConstraint) c.addInitialConstraint(initialConstraint)
@@ -66,11 +62,11 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
private fun addSubTypeConstraintAndIncorporateIt( private fun addSubTypeConstraintAndIncorporateIt(
c: Context, c: Context,
lowerType: UnwrappedType, lowerType: KotlinTypeMarker,
upperType: UnwrappedType, upperType: KotlinTypeMarker,
incorporatePosition: IncorporationConstraintPosition incorporatePosition: IncorporationConstraintPosition
) { ) {
val possibleNewConstraints = Stack<Pair<NewTypeVariable, Constraint>>() val possibleNewConstraints = Stack<Pair<TypeVariableMarker, Constraint>>()
val typeCheckerContext = TypeCheckerContext(c, incorporatePosition, lowerType, upperType, possibleNewConstraints) val typeCheckerContext = TypeCheckerContext(c, incorporatePosition, lowerType, upperType, possibleNewConstraints)
typeCheckerContext.runIsSubtypeOf(lowerType, upperType) typeCheckerContext.runIsSubtypeOf(lowerType, upperType)
@@ -79,7 +75,7 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
if (c.shouldWeSkipConstraint(typeVariable, constraint)) continue if (c.shouldWeSkipConstraint(typeVariable, constraint)) continue
val constraints = val constraints =
c.notFixedTypeVariables[typeVariable.freshTypeConstructor] ?: typeCheckerContext.fixedTypeVariable(typeVariable) c.notFixedTypeVariables[typeVariable.freshTypeConstructor(c)] ?: typeCheckerContext.fixedTypeVariable(typeVariable)
// it is important, that we add constraint here(not inside TypeCheckerContext), because inside incorporation we read constraints // it is important, that we add constraint here(not inside TypeCheckerContext), because inside incorporation we read constraints
constraints.addConstraint(constraint)?.let { constraints.addConstraint(constraint)?.let {
@@ -88,59 +84,71 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
} }
} }
private fun updateAllowedTypeDepth(c: Context, initialType: UnwrappedType) { private fun updateAllowedTypeDepth(c: Context, initialType: KotlinTypeMarker) = with(c) {
c.maxTypeDepthFromInitialConstraints = Math.max(c.maxTypeDepthFromInitialConstraints, initialType.typeDepth()) c.maxTypeDepthFromInitialConstraints = Math.max(c.maxTypeDepthFromInitialConstraints, initialType.typeDepth())
} }
private fun Context.shouldWeSkipConstraint(typeVariable: NewTypeVariable, constraint: Constraint): Boolean { private fun Context.shouldWeSkipConstraint(typeVariable: TypeVariableMarker, constraint: Constraint): Boolean {
assert(constraint.kind != ConstraintKind.EQUALITY) assert(constraint.kind != ConstraintKind.EQUALITY)
val constraintType = constraint.type val constraintType = constraint.type
if (!isAllowedType(constraintType)) return true if (!isAllowedType(constraintType)) return true
if (constraintType.constructor == typeVariable.freshTypeConstructor) { if (constraintType.typeConstructor() == typeVariable.freshTypeConstructor()) {
if (constraintType.lowerIfFlexible().isMarkedNullable && constraint.kind == LOWER) return false // T? <: T if (constraintType.lowerBoundIfFlexible().isMarkedNullable() && constraint.kind == LOWER) return false // T? <: T
return true // T <: T(?!) return true // T <: T(?!)
} }
if (constraintType is SimpleType) { if (constraintType.isSimpleType()) {
if (constraint.kind == UPPER && constraintType.isNullableAny()) return true // T <: Any? if (constraint.kind == UPPER && constraintType.isNullableAny()) return true // T <: Any?
} }
return false return false
} }
private fun Context.isAllowedType(type: UnwrappedType) = private fun Context.isAllowedType(type: KotlinTypeMarker) =
type.typeDepth() <= maxTypeDepthFromInitialConstraints + ALLOWED_DEPTH_DELTA_FOR_INCORPORATION type.typeDepth() <= maxTypeDepthFromInitialConstraints + ALLOWED_DEPTH_DELTA_FOR_INCORPORATION
private inner class TypeCheckerContext( private inner class TypeCheckerContext(
val c: Context, val c: Context,
val position: IncorporationConstraintPosition, val position: IncorporationConstraintPosition,
val baseLowerType: UnwrappedType, val baseLowerType: KotlinTypeMarker,
val baseUpperType: UnwrappedType, val baseUpperType: KotlinTypeMarker,
val possibleNewConstraints: MutableList<Pair<NewTypeVariable, Constraint>> val possibleNewConstraints: MutableList<Pair<TypeVariableMarker, Constraint>>
) : TypeCheckerContextForConstraintSystem(), ConstraintIncorporator.Context { ) : AbstractTypeCheckerContextForConstraintSystem(), ConstraintIncorporator.Context, TypeSystemInferenceExtensionContext by c {
fun runIsSubtypeOf(lowerType: UnwrappedType, upperType: UnwrappedType) { val baseContext: AbstractTypeCheckerContext = newBaseTypeCheckerContext(isErrorTypeEqualsToAnything)
with(NewKotlinTypeChecker) {
if (!this@TypeCheckerContext.isSubtypeOf(lowerType, upperType)) { override fun substitutionSupertypePolicy(type: SimpleTypeMarker): SupertypesPolicy.DoCustomTransform {
// todo improve error reporting -- add information about base types return baseContext.substitutionSupertypePolicy(type)
c.addError(NewConstraintError(lowerType, upperType, position)) }
}
override fun areEqualTypeConstructors(a: TypeConstructorMarker, b: TypeConstructorMarker): Boolean {
return baseContext.areEqualTypeConstructors(a, b)
}
override fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker {
return baseContext.prepareType(type)
}
fun runIsSubtypeOf(lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker) {
if (!AbstractTypeChecker.isSubtypeOf(this@TypeCheckerContext as AbstractTypeCheckerContext, lowerType, upperType)) {
// todo improve error reporting -- add information about base types
c.addError(NewConstraintError(lowerType, upperType, position))
} }
} }
// from TypeCheckerContextForConstraintSystem // from AbstractTypeCheckerContextForConstraintSystem
override fun isMyTypeVariable(type: SimpleType): Boolean = c.allTypeVariables.containsKey(type.constructor) override fun isMyTypeVariable(type: SimpleTypeMarker): Boolean = c.allTypeVariables.containsKey(type.typeConstructor())
override fun addUpperConstraint(typeVariable: TypeConstructor, superType: UnwrappedType) = override fun addUpperConstraint(typeVariable: TypeConstructorMarker, superType: KotlinTypeMarker) =
addConstraint(typeVariable, superType, UPPER) addConstraint(typeVariable, superType, UPPER)
override fun addLowerConstraint(typeVariable: TypeConstructor, subType: UnwrappedType) = override fun addLowerConstraint(typeVariable: TypeConstructorMarker, subType: KotlinTypeMarker) =
addConstraint(typeVariable, subType, LOWER) addConstraint(typeVariable, subType, LOWER)
private fun isCapturedTypeFromSubtyping(type: UnwrappedType) = private fun isCapturedTypeFromSubtyping(type: KotlinTypeMarker) =
when ((type as? NewCapturedType)?.captureStatus) { when ((type as? NewCapturedType)?.captureStatus) {
null, CaptureStatus.FROM_EXPRESSION -> false null, CaptureStatus.FROM_EXPRESSION -> false
CaptureStatus.FOR_SUBTYPING -> true CaptureStatus.FOR_SUBTYPING -> true
@@ -148,12 +156,12 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
error("Captured type for incorporation shouldn't escape from incorporation: $type\n" + renderBaseConstraint()) error("Captured type for incorporation shouldn't escape from incorporation: $type\n" + renderBaseConstraint())
} }
private fun addConstraint(typeVariableConstructor: TypeConstructor, type: UnwrappedType, kind: ConstraintKind) { private fun addConstraint(typeVariableConstructor: TypeConstructorMarker, type: KotlinTypeMarker, kind: ConstraintKind) {
val typeVariable = c.allTypeVariables[typeVariableConstructor] val typeVariable = c.allTypeVariables[typeVariableConstructor]
?: error("Should by type variableConstructor: $typeVariableConstructor. ${c.allTypeVariables.values}") ?: error("Should by type variableConstructor: $typeVariableConstructor. ${c.allTypeVariables.values}")
var targetType = type var targetType = type
if (targetType.isError) { if (targetType.isError()) {
c.addError(ConstrainingTypeIsError(typeVariable, targetType, position)) c.addError(ConstrainingTypeIsError(typeVariable, targetType, position))
return return
} }
@@ -163,7 +171,7 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
if (kind == UPPER) { if (kind == UPPER) {
val subType = val subType =
typeApproximator.approximateToSubType(type, TypeApproximatorConfiguration.SubtypeCapturedTypesApproximation) typeApproximator.approximateToSubType(type, TypeApproximatorConfiguration.SubtypeCapturedTypesApproximation)
if (subType != null && !KotlinBuiltIns.isNothingOrNullableNothing(subType)) { if (subType != null && !subType.typeConstructor().isNothingConstructor()) {
targetType = subType targetType = subType
} }
} }
@@ -171,7 +179,7 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
if (kind == LOWER) { if (kind == LOWER) {
val superType = val superType =
typeApproximator.approximateToSuperType(type, TypeApproximatorConfiguration.SubtypeCapturedTypesApproximation) typeApproximator.approximateToSuperType(type, TypeApproximatorConfiguration.SubtypeCapturedTypesApproximation)
if (superType != null && !KotlinBuiltIns.isAnyOrNullableAny(superType)) { // todo rethink error reporting for Any cases if (superType != null && !superType.typeConstructor().isAnyConstructor()) { // todo rethink error reporting for Any cases
targetType = superType targetType = superType
} }
} }
@@ -186,7 +194,7 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
} }
// from ConstraintIncorporator.Context // from ConstraintIncorporator.Context
override fun addNewIncorporatedConstraint(lowerType: UnwrappedType, upperType: UnwrappedType) { override fun addNewIncorporatedConstraint(lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker) {
if (c.isAllowedType(lowerType) && c.isAllowedType(upperType)) { if (c.isAllowedType(lowerType) && c.isAllowedType(upperType)) {
runIsSubtypeOf(lowerType, upperType) runIsSubtypeOf(lowerType, upperType)
} }
@@ -195,7 +203,7 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
override val allTypeVariablesWithConstraints: Collection<VariableWithConstraints> override val allTypeVariablesWithConstraints: Collection<VariableWithConstraints>
get() = c.notFixedTypeVariables.values get() = c.notFixedTypeVariables.values
override fun getTypeVariable(typeConstructor: TypeConstructor): NewTypeVariable? { override fun getTypeVariable(typeConstructor: TypeConstructorMarker): TypeVariableMarker? {
val typeVariable = c.allTypeVariables[typeConstructor] val typeVariable = c.allTypeVariables[typeConstructor]
if (typeVariable != null && !c.notFixedTypeVariables.containsKey(typeConstructor)) { if (typeVariable != null && !c.notFixedTypeVariables.containsKey(typeConstructor)) {
fixedTypeVariable(typeVariable) fixedTypeVariable(typeVariable)
@@ -203,11 +211,11 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
return typeVariable return typeVariable
} }
override fun getConstraintsForVariable(typeVariable: NewTypeVariable) = override fun getConstraintsForVariable(typeVariable: TypeVariableMarker) =
c.notFixedTypeVariables[typeVariable.freshTypeConstructor]?.constraints c.notFixedTypeVariables[typeVariable.freshTypeConstructor()]?.constraints
?: fixedTypeVariable(typeVariable) ?: fixedTypeVariable(typeVariable)
fun fixedTypeVariable(variable: NewTypeVariable): Nothing { fun fixedTypeVariable(variable: TypeVariableMarker): Nothing {
error( error(
"Type variable $variable should not be fixed!\n" + "Type variable $variable should not be fixed!\n" +
renderBaseConstraint() renderBaseConstraint()
@@ -11,7 +11,11 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraint
import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.types.TypeConstructor import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
import org.jetbrains.kotlin.types.model.TypeVariableMarker
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -25,19 +29,19 @@ class KotlinConstraintSystemCompleter(
} }
interface Context : VariableFixationFinder.Context, ResultTypeResolver.Context { interface Context : VariableFixationFinder.Context, ResultTypeResolver.Context {
override val notFixedTypeVariables: Map<TypeConstructor, VariableWithConstraints> override val notFixedTypeVariables: Map<TypeConstructorMarker, VariableWithConstraints>
override val postponedTypeVariables: List<NewTypeVariable> override val postponedTypeVariables: List<TypeVariableMarker>
// type can be proper if it not contains not fixed type variables // type can be proper if it not contains not fixed type variables
fun canBeProper(type: UnwrappedType): Boolean fun canBeProper(type: KotlinTypeMarker): Boolean
fun containsOnlyFixedOrPostponedVariables(type: UnwrappedType): Boolean fun containsOnlyFixedOrPostponedVariables(type: KotlinTypeMarker): Boolean
// mutable operations // mutable operations
fun addError(error: KotlinCallDiagnostic) fun addError(error: KotlinCallDiagnostic)
fun fixVariable(variable: NewTypeVariable, resultType: UnwrappedType) fun fixVariable(variable: TypeVariableMarker, resultType: KotlinTypeMarker)
} }
fun runCompletion( fun runCompletion(
@@ -157,7 +161,7 @@ class KotlinConstraintSystemCompleter(
c: Context, c: Context,
collectVariablesFromContext: Boolean, collectVariablesFromContext: Boolean,
topLevelAtoms: List<ResolvedAtom> topLevelAtoms: List<ResolvedAtom>
): List<TypeConstructor> { ): List<TypeConstructorMarker> {
if (collectVariablesFromContext) return c.notFixedTypeVariables.keys.toList() if (collectVariablesFromContext) return c.notFixedTypeVariables.keys.toList()
fun ResolvedAtom.process(to: LinkedHashSet<TypeConstructor>) { fun ResolvedAtom.process(to: LinkedHashSet<TypeConstructor>) {
@@ -12,8 +12,9 @@ import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.NewCapturedType import org.jetbrains.kotlin.types.checker.NewCapturedType
import org.jetbrains.kotlin.types.checker.NewCapturedTypeConstructor import org.jetbrains.kotlin.types.checker.NewCapturedTypeConstructor
import org.jetbrains.kotlin.types.checker.intersectTypes import org.jetbrains.kotlin.types.checker.intersectTypes
import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker
interface NewTypeSubstitutor { interface NewTypeSubstitutor: TypeSubstitutorMarker {
fun substituteNotNullTypeWithConstructor(constructor: TypeConstructor): UnwrappedType? fun substituteNotNullTypeWithConstructor(constructor: TypeConstructor): UnwrappedType?
fun safeSubstitute(type: UnwrappedType): UnwrappedType = substitute(type, runCapturedChecks = true, keepAnnotation = false) ?: type fun safeSubstitute(type: UnwrappedType): UnwrappedType = substitute(type, runCapturedChecks = true, keepAnnotation = false) ?: type
@@ -24,33 +24,31 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraint
import org.jetbrains.kotlin.resolve.calls.inference.model.checkConstraint import org.jetbrains.kotlin.resolve.calls.inference.model.checkConstraint
import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.intersectTypes import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.checker.isIntegerLiteralType import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext
import org.jetbrains.kotlin.types.typeUtil.contains
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class ResultTypeResolver( class ResultTypeResolver(
val typeApproximator: TypeApproximator, val typeApproximator: TypeApproximator,
val trivialConstraintTypeInferenceOracle: TrivialConstraintTypeInferenceOracle val trivialConstraintTypeInferenceOracle: TrivialConstraintTypeInferenceOracle
) { ) {
interface Context { interface Context : TypeSystemInferenceExtensionContext {
fun isProperType(type: UnwrappedType): Boolean fun isProperType(type: KotlinTypeMarker): Boolean
} }
fun findResultType(c: Context, variableWithConstraints: VariableWithConstraints, direction: ResolveDirection): UnwrappedType { fun findResultType(c: Context, variableWithConstraints: VariableWithConstraints, direction: ResolveDirection): KotlinTypeMarker {
findResultTypeOrNull(c, variableWithConstraints, direction)?.let { return it } findResultTypeOrNull(c, variableWithConstraints, direction)?.let { return it }
// no proper constraints // no proper constraints
return variableWithConstraints.typeVariable.freshTypeConstructor.builtIns.run { return run {
if (direction == ResolveDirection.TO_SUBTYPE) nothingType else nullableAnyType if (direction == ResolveDirection.TO_SUBTYPE) c.nothingType() else c.nullableAnyType()
} }
} }
fun findResultTypeOrNull(c: Context, variableWithConstraints: VariableWithConstraints, direction: ResolveDirection): UnwrappedType? { fun findResultTypeOrNull(c: Context, variableWithConstraints: VariableWithConstraints, direction: ResolveDirection): KotlinTypeMarker? {
findResultIfThereIsEqualsConstraint(c, variableWithConstraints)?.let { return it } findResultIfThereIsEqualsConstraint(c, variableWithConstraints)?.let { return it }
val subType = findSubType(c, variableWithConstraints) val subType = c.findSubType(variableWithConstraints)
val superType = findSuperType(c, variableWithConstraints) val superType = c.findSuperType(variableWithConstraints)
val result = if (direction == ResolveDirection.TO_SUBTYPE || direction == ResolveDirection.UNKNOWN) { val result = if (direction == ResolveDirection.TO_SUBTYPE || direction == ResolveDirection.UNKNOWN) {
c.resultType(subType, superType, variableWithConstraints) c.resultType(subType, superType, variableWithConstraints)
} else { } else {
@@ -61,10 +59,10 @@ class ResultTypeResolver(
} }
private fun Context.resultType( private fun Context.resultType(
firstCandidate: UnwrappedType?, firstCandidate: KotlinTypeMarker?,
secondCandidate: UnwrappedType?, secondCandidate: KotlinTypeMarker?,
variableWithConstraints: VariableWithConstraints variableWithConstraints: VariableWithConstraints
): UnwrappedType? { ): KotlinTypeMarker? {
if (firstCandidate == null || secondCandidate == null) return firstCandidate ?: secondCandidate if (firstCandidate == null || secondCandidate == null) return firstCandidate ?: secondCandidate
if (isSuitableType(firstCandidate, variableWithConstraints)) return firstCandidate if (isSuitableType(firstCandidate, variableWithConstraints)) return firstCandidate
@@ -76,7 +74,7 @@ class ResultTypeResolver(
} }
} }
private fun Context.isSuitableType(resultType: UnwrappedType, variableWithConstraints: VariableWithConstraints): Boolean { private fun Context.isSuitableType(resultType: KotlinTypeMarker, variableWithConstraints: VariableWithConstraints): Boolean {
for (constraint in variableWithConstraints.constraints) { for (constraint in variableWithConstraints.constraints) {
if (!isProperType(constraint.type)) continue if (!isProperType(constraint.type)) continue
if (!checkConstraint(constraint.type, constraint.kind, resultType)) return false if (!checkConstraint(constraint.type, constraint.kind, resultType)) return false
@@ -87,11 +85,11 @@ class ResultTypeResolver(
return true return true
} }
private fun findSubType(c: Context, variableWithConstraints: VariableWithConstraints): UnwrappedType? { private fun Context.findSubType(variableWithConstraints: VariableWithConstraints): KotlinTypeMarker? {
val lowerConstraints = variableWithConstraints.constraints.filter { it.kind == ConstraintKind.LOWER && c.isProperType(it.type) } val lowerConstraints = variableWithConstraints.constraints.filter { it.kind == ConstraintKind.LOWER && isProperType(it.type) }
if (lowerConstraints.isNotEmpty()) { if (lowerConstraints.isNotEmpty()) {
val types = sinkIntegerLiteralTypes(lowerConstraints.map { it.type }) val types = sinkIntegerLiteralTypes(lowerConstraints.map { it.type })
val commonSuperType = NewCommonSuperTypeCalculator.commonSuperType(types) val commonSuperType = with(NewCommonSuperTypeCalculator) { commonSuperType(types) }
/** /**
* *
* fun <T> Array<out T>.intersect(other: Iterable<T>) { * fun <T> Array<out T>.intersect(other: Iterable<T>) {
@@ -119,16 +117,16 @@ class ResultTypeResolver(
return null return null
} }
private fun sinkIntegerLiteralTypes(types: List<UnwrappedType>): List<UnwrappedType> { private fun Context.sinkIntegerLiteralTypes(types: List<KotlinTypeMarker>): List<KotlinTypeMarker> {
return types.sortedBy { type -> return types.sortedBy { type ->
val containsILT = type.contains { it.unwrap().safeAs<SimpleType>()?.isIntegerLiteralType ?: false } val containsILT = type.contains { it.asSimpleType()?.isIntegerLiteralType() ?: false }
if (containsILT) 1 else 0 if (containsILT) 1 else 0
} }
} }
private fun findSuperType(c: Context, variableWithConstraints: VariableWithConstraints): UnwrappedType? { private fun Context.findSuperType(variableWithConstraints: VariableWithConstraints): KotlinTypeMarker? {
val upperConstraints = variableWithConstraints.constraints.filter { it.kind == ConstraintKind.UPPER && c.isProperType(it.type) } val upperConstraints = variableWithConstraints.constraints.filter { it.kind == ConstraintKind.UPPER && this@findSuperType.isProperType(it.type) }
if (upperConstraints.isNotEmpty()) { if (upperConstraints.isNotEmpty()) {
val upperType = intersectTypes(upperConstraints.map { it.type }) val upperType = intersectTypes(upperConstraints.map { it.type })
@@ -137,22 +135,22 @@ class ResultTypeResolver(
return null return null
} }
fun findResultIfThereIsEqualsConstraint(c: Context, variableWithConstraints: VariableWithConstraints): UnwrappedType? { fun findResultIfThereIsEqualsConstraint(c: Context, variableWithConstraints: VariableWithConstraints): KotlinTypeMarker? = with(c) {
val properEqualityConstraints = variableWithConstraints.constraints.filter { val properEqualityConstraints = variableWithConstraints.constraints.filter {
it.kind == ConstraintKind.EQUALITY && c.isProperType(it.type) it.kind == ConstraintKind.EQUALITY && c.isProperType(it.type)
} }
return representativeFromEqualityConstraints(properEqualityConstraints) return c.representativeFromEqualityConstraints(properEqualityConstraints)
} }
// Discriminate integer literal types as they are less specific than separate integer types (Int, Short...) // Discriminate integer literal types as they are less specific than separate integer types (Int, Short...)
private fun representativeFromEqualityConstraints(constraints: List<Constraint>): UnwrappedType? { private fun Context.representativeFromEqualityConstraints(constraints: List<Constraint>): KotlinTypeMarker? {
if (constraints.isEmpty()) return null if (constraints.isEmpty()) return null
val constraintTypes = constraints.map { it.type } val constraintTypes = constraints.map { it.type }
val nonLiteralTypes = constraintTypes.filter { it.constructor !is IntegerLiteralTypeConstructor } val nonLiteralTypes = constraintTypes.filter { it.typeConstructor() !is IntegerLiteralTypeConstructor }
return nonLiteralTypes.singleBestRepresentative()?.unwrap() return nonLiteralTypes.singleBestRepresentative()
?: constraintTypes.singleBestRepresentative()?.unwrap() ?: constraintTypes.singleBestRepresentative()
?: constraintTypes.first() // seems like constraint system has contradiction ?: constraintTypes.first() // seems like constraint system has contradiction
} }
} }
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.resolve.calls.inference.components
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.resolve.calls.components.ClassicTypeSystemContextForCS
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition
@@ -31,7 +32,8 @@ import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
class SimpleConstraintSystemImpl(constraintInjector: ConstraintInjector, builtIns: KotlinBuiltIns) : SimpleConstraintSystem { class SimpleConstraintSystemImpl(constraintInjector: ConstraintInjector, builtIns: KotlinBuiltIns) : SimpleConstraintSystem {
val csBuilder: ConstraintSystemBuilder = NewConstraintSystemImpl(constraintInjector, builtIns).getBuilder() val csBuilder: ConstraintSystemBuilder =
NewConstraintSystemImpl(constraintInjector, ClassicTypeSystemContextForCS(builtIns)).getBuilder()
override fun registerTypeVariables(typeParameters: Collection<TypeParameterDescriptor>): TypeSubstitutor { override fun registerTypeVariables(typeParameters: Collection<TypeParameterDescriptor>): TypeSubstitutor {
val substitutionMap = typeParameters.associate { val substitutionMap = typeParameters.associate {
@@ -7,26 +7,29 @@ package org.jetbrains.kotlin.resolve.calls.inference.components
import org.jetbrains.kotlin.resolve.calls.inference.model.Constraint import org.jetbrains.kotlin.resolve.calls.inference.model.Constraint
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext
import org.jetbrains.kotlin.types.typeUtil.contains import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContextDelegate
import org.jetbrains.kotlin.types.typeUtil.isNothing
import org.jetbrains.kotlin.types.typeUtil.isNullableNothing
class TrivialConstraintTypeInferenceOracle { class TrivialConstraintTypeInferenceOracle(context: TypeSystemInferenceExtensionContextDelegate) :
TypeSystemInferenceExtensionContext by context {
// The idea is to add knowledge that constraint `Nothing(?) <: T` is quite useless and // The idea is to add knowledge that constraint `Nothing(?) <: T` is quite useless and
// it's totally fine to go and resolve postponed argument without fixation T to Nothing(?). // it's totally fine to go and resolve postponed argument without fixation T to Nothing(?).
// In other words, constraint `Nothing(?) <: T` is *not* proper // In other words, constraint `Nothing(?) <: T` is *not* proper
fun isTrivialConstraint(constraint: Constraint): Boolean { fun isTrivialConstraint(
constraint: Constraint
): Boolean {
// TODO: probably we also can take into account `T <: Any(?)` constraints // TODO: probably we also can take into account `T <: Any(?)` constraints
return constraint.kind == ConstraintKind.LOWER && constraint.type.isNothingOrNullableNothing() return constraint.kind == ConstraintKind.LOWER && constraint.type.typeConstructor().isNothingConstructor()
} }
// This function controls the choice between sub and super result type // This function controls the choice between sub and super result type
// Even that Nothing(?) is the most specific type for subtype, it doesn't bring valuable information to the user, // Even that Nothing(?) is the most specific type for subtype, it doesn't bring valuable information to the user,
// therefore it is discriminated in favor of supertype // therefore it is discriminated in favor of supertype
fun isSuitableResultedType(resultType: UnwrappedType): Boolean { fun isSuitableResultedType(
return !resultType.isNothingOrNullableNothing() resultType: KotlinTypeMarker
): Boolean {
return !resultType.typeConstructor().isNothingConstructor()
} }
// It's possible to generate Nothing-like constraints inside incorporation mechanism: // It's possible to generate Nothing-like constraints inside incorporation mechanism:
@@ -36,7 +39,7 @@ class TrivialConstraintTypeInferenceOracle {
// Therefore, here we avoid adding such trivial constraints to have stable constraint system // Therefore, here we avoid adding such trivial constraints to have stable constraint system
fun isGeneratedConstraintTrivial( fun isGeneratedConstraintTrivial(
otherConstraint: Constraint, otherConstraint: Constraint,
generatedConstraintType: UnwrappedType generatedConstraintType: KotlinTypeMarker
): Boolean { ): Boolean {
if (generatedConstraintType.isNothing()) return true if (generatedConstraintType.isNothing()) return true
@@ -49,10 +52,13 @@ class TrivialConstraintTypeInferenceOracle {
return false return false
} }
private fun KotlinTypeMarker.isNothingOrNullableNothing(): Boolean =
typeConstructor().isNothingConstructor()
private fun KotlinTypeMarker.containsOnlyNonNullableNothing(): Boolean =
contains { it.isNothing() } && !contains { it.isNullableNothing() }
} }
private fun UnwrappedType.isNothingOrNullableNothing(): Boolean =
isNothing() || isNullableNothing()
private fun UnwrappedType.containsOnlyNonNullableNothing(): Boolean =
contains { it.isNothing() } && !contains { it.isNullableNothing() }
@@ -18,24 +18,26 @@ package org.jetbrains.kotlin.resolve.calls.inference.components
import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraints import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraints
import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtom import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtom
import org.jetbrains.kotlin.types.TypeConstructor import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.model.TypeConstructorMarker
import org.jetbrains.kotlin.types.typeUtil.contains import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext
import org.jetbrains.kotlin.types.model.freshTypeConstructor
import org.jetbrains.kotlin.utils.SmartSet import org.jetbrains.kotlin.utils.SmartSet
class TypeVariableDependencyInformationProvider( class TypeVariableDependencyInformationProvider(
private val notFixedTypeVariables: Map<TypeConstructor, VariableWithConstraints>, private val notFixedTypeVariables: Map<TypeConstructorMarker, VariableWithConstraints>,
private val postponedKtPrimitives: List<PostponedResolvedAtom>, private val postponedKtPrimitives: List<PostponedResolvedAtom>,
private val topLevelType: UnwrappedType? private val topLevelType: KotlinTypeMarker?,
private val typeSystemContext: TypeSystemInferenceExtensionContext
) { ) {
// not oriented edges // not oriented edges
private val constrainEdges: MutableMap<TypeConstructor, MutableSet<TypeConstructor>> = hashMapOf() private val constrainEdges: MutableMap<TypeConstructorMarker, MutableSet<TypeConstructorMarker>> = hashMapOf()
// oriented edges // oriented edges
private val postponeArgumentsEdges: MutableMap<TypeConstructor, MutableSet<TypeConstructor>> = hashMapOf() private val postponeArgumentsEdges: MutableMap<TypeConstructorMarker, MutableSet<TypeConstructorMarker>> = hashMapOf()
private val relatedToAllOutputTypes: MutableSet<TypeConstructor> = hashSetOf() private val relatedToAllOutputTypes: MutableSet<TypeConstructorMarker> = hashSetOf()
private val relatedToTopLevelType: MutableSet<TypeConstructor> = hashSetOf() private val relatedToTopLevelType: MutableSet<TypeConstructorMarker> = hashSetOf()
init { init {
computeConstraintEdges() computeConstraintEdges()
@@ -44,17 +46,17 @@ class TypeVariableDependencyInformationProvider(
computeRelatedToTopLevelType() computeRelatedToTopLevelType()
} }
fun isVariableRelatedToTopLevelType(variable: TypeConstructor) = relatedToTopLevelType.contains(variable) fun isVariableRelatedToTopLevelType(variable: TypeConstructorMarker) = relatedToTopLevelType.contains(variable)
fun isVariableRelatedToAnyOutputType(variable: TypeConstructor) = relatedToAllOutputTypes.contains(variable) fun isVariableRelatedToAnyOutputType(variable: TypeConstructorMarker) = relatedToAllOutputTypes.contains(variable)
private fun computeConstraintEdges() { private fun computeConstraintEdges() {
fun addConstraintEdge(from: TypeConstructor, to: TypeConstructor) { fun addConstraintEdge(from: TypeConstructorMarker, to: TypeConstructorMarker) {
constrainEdges.getOrPut(from) { hashSetOf() }.add(to) constrainEdges.getOrPut(from) { hashSetOf() }.add(to)
constrainEdges.getOrPut(to) { hashSetOf() }.add(from) constrainEdges.getOrPut(to) { hashSetOf() }.add(from)
} }
for (variableWithConstraints in notFixedTypeVariables.values) { for (variableWithConstraints in notFixedTypeVariables.values) {
val from = variableWithConstraints.typeVariable.freshTypeConstructor val from = variableWithConstraints.typeVariable.freshTypeConstructor(typeSystemContext)
for (constraint in variableWithConstraints.constraints) { for (constraint in variableWithConstraints.constraints) {
constraint.type.forAllMyTypeVariables { constraint.type.forAllMyTypeVariables {
@@ -67,14 +69,14 @@ class TypeVariableDependencyInformationProvider(
} }
private fun computePostponeArgumentsEdges() { private fun computePostponeArgumentsEdges() {
fun addPostponeArgumentsEdges(from: TypeConstructor, to: TypeConstructor) { fun addPostponeArgumentsEdges(from: TypeConstructorMarker, to: TypeConstructorMarker) {
postponeArgumentsEdges.getOrPut(from) { hashSetOf() }.add(to) postponeArgumentsEdges.getOrPut(from) { hashSetOf() }.add(to)
} }
for (argument in postponedKtPrimitives) { for (argument in postponedKtPrimitives) {
if (argument.analyzed) continue if (argument.analyzed) continue
val typeVariablesInOutputType = SmartSet.create<TypeConstructor>() val typeVariablesInOutputType = SmartSet.create<TypeConstructorMarker>()
(argument.outputType ?: continue).forAllMyTypeVariables { typeVariablesInOutputType.add(it) } (argument.outputType ?: continue).forAllMyTypeVariables { typeVariablesInOutputType.add(it) }
if (typeVariablesInOutputType.isEmpty()) continue if (typeVariablesInOutputType.isEmpty()) continue
@@ -104,18 +106,21 @@ class TypeVariableDependencyInformationProvider(
} }
} }
private fun isMyTypeVariable(typeConstructor: TypeConstructor) = notFixedTypeVariables.containsKey(typeConstructor) private fun isMyTypeVariable(typeConstructor: TypeConstructorMarker) = notFixedTypeVariables.containsKey(typeConstructor)
private fun UnwrappedType.forAllMyTypeVariables(action: (TypeConstructor) -> Unit) = this.contains { private fun KotlinTypeMarker.forAllMyTypeVariables(action: (TypeConstructorMarker) -> Unit) =
if (isMyTypeVariable(it.constructor)) action(it.constructor) with(typeSystemContext) {
contains {
if (isMyTypeVariable(it.typeConstructor())) action(it.typeConstructor())
false
}
}
false
}
private fun getConstraintEdges(from: TypeConstructor): Set<TypeConstructor> = constrainEdges[from] ?: emptySet() private fun getConstraintEdges(from: TypeConstructorMarker): Set<TypeConstructorMarker> = constrainEdges[from] ?: emptySet()
private fun getPostponeEdges(from: TypeConstructor): Set<TypeConstructor> = postponeArgumentsEdges[from] ?: emptySet() private fun getPostponeEdges(from: TypeConstructorMarker): Set<TypeConstructorMarker> = postponeArgumentsEdges[from] ?: emptySet()
private fun addAllRelatedNodes(to: MutableSet<TypeConstructor>, node: TypeConstructor, includePostponedEdges: Boolean) { private fun addAllRelatedNodes(to: MutableSet<TypeConstructorMarker>, node: TypeConstructorMarker, includePostponedEdges: Boolean) {
if (to.add(node)) { if (to.add(node)) {
for (relatedNode in getConstraintEdges(node)) { for (relatedNode in getConstraintEdges(node)) {
addAllRelatedNodes(to, relatedNode, includePostponedEdges) addAllRelatedNodes(to, relatedNode, includePostponedEdges)
@@ -20,12 +20,11 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.Constraint
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind
import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraints import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraints
import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtom import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtom
import org.jetbrains.kotlin.types.FlexibleType import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.SimpleType import org.jetbrains.kotlin.types.model.FlexibleTypeMarker
import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.model.SimpleTypeMarker
import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker import org.jetbrains.kotlin.types.model.TypeVariance
import org.jetbrains.kotlin.types.checker.isIntersectionType
import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.kotlin.utils.SmartList
@@ -34,7 +33,7 @@ private typealias Variable = VariableWithConstraints
class TypeVariableDirectionCalculator( class TypeVariableDirectionCalculator(
private val c: VariableFixationFinder.Context, private val c: VariableFixationFinder.Context,
private val postponedKtPrimitives: List<PostponedResolvedAtom>, private val postponedKtPrimitives: List<PostponedResolvedAtom>,
topLevelType: UnwrappedType topLevelType: KotlinTypeMarker
) { ) {
enum class ResolveDirection { enum class ResolveDirection {
TO_SUBTYPE, TO_SUBTYPE,
@@ -55,7 +54,7 @@ class TypeVariableDirectionCalculator(
fun getDirection(typeVariable: Variable): ResolveDirection = fun getDirection(typeVariable: Variable): ResolveDirection =
directions.getOrDefault(typeVariable, ResolveDirection.UNKNOWN) directions.getOrDefault(typeVariable, ResolveDirection.UNKNOWN)
private fun setupDirections(topReturnType: UnwrappedType) { private fun setupDirections(topReturnType: KotlinTypeMarker) {
topReturnType.visitType(ResolveDirection.TO_SUBTYPE) { variableWithConstraints, direction -> topReturnType.visitType(ResolveDirection.TO_SUBTYPE) { variableWithConstraints, direction ->
enterToNode(variableWithConstraints, direction) enterToNode(variableWithConstraints, direction)
} }
@@ -105,47 +104,54 @@ class TypeVariableDirectionCalculator(
!(direction == ResolveDirection.TO_SUBTYPE && constraint.kind == ConstraintKind.UPPER) && !(direction == ResolveDirection.TO_SUBTYPE && constraint.kind == ConstraintKind.UPPER) &&
!(direction == ResolveDirection.TO_SUPERTYPE && constraint.kind == ConstraintKind.LOWER) !(direction == ResolveDirection.TO_SUPERTYPE && constraint.kind == ConstraintKind.LOWER)
private fun UnwrappedType.visitType( private fun KotlinTypeMarker.visitType(
startDirection: ResolveDirection, startDirection: ResolveDirection,
action: (variable: Variable, direction: ResolveDirection) -> Unit action: (variable: Variable, direction: ResolveDirection) -> Unit
) = ) = when (this) {
when (this) { is SimpleTypeMarker -> visitType(startDirection, action)
is SimpleType -> visitType(startDirection, action) is FlexibleTypeMarker -> {
is FlexibleType -> { with(c) {
lowerBound.visitType(startDirection, action) lowerBound().visitType(startDirection, action)
upperBound.visitType(startDirection, action) upperBound().visitType(startDirection, action)
} }
} }
else -> error("?!")
}
private fun SimpleType.visitType(startDirection: ResolveDirection, action: (variable: Variable, direction: ResolveDirection) -> Unit) { private fun SimpleTypeMarker.visitType(
if (isIntersectionType) { startDirection: ResolveDirection,
constructor.supertypes.forEach { action: (variable: Variable, direction: ResolveDirection) -> Unit
it.unwrap().visitType(startDirection, action) ): Unit = with(c) {
val constructor = typeConstructor()
if (constructor.isIntersection()) {
constructor.supertypes().forEach {
it.visitType(startDirection, action)
} }
return return
} }
if (arguments.isEmpty()) { if (argumentsCount() == 0) {
c.notFixedTypeVariables[constructor]?.let { c.notFixedTypeVariables[constructor]?.let {
action(it, startDirection) action(it, startDirection)
} }
return return
} }
val parameters = constructor.parameters if (constructor.parametersCount() != argumentsCount()) return // incorrect type
if (parameters.size != arguments.size) return // incorrect type
for ((argument, parameter) in arguments.zip(parameters)) { for (index in 0 until constructor.parametersCount()) {
if (argument.isStarProjection) continue val parameter = constructor.getParameter(index)
val argument = getArgument(index)
if (argument.isStarProjection()) continue
val variance = NewKotlinTypeChecker.effectiveVariance(parameter.variance, argument.projectionKind) ?: Variance.INVARIANT val variance = AbstractTypeChecker.effectiveVariance(parameter.getVariance(), argument.getVariance()) ?: TypeVariance.INV
val innerDirection = when (variance) { val innerDirection = when (variance) {
Variance.INVARIANT -> ResolveDirection.UNKNOWN TypeVariance.INV -> ResolveDirection.UNKNOWN
Variance.OUT_VARIANCE -> startDirection TypeVariance.OUT -> startDirection
Variance.IN_VARIANCE -> startDirection.opposite() TypeVariance.IN -> startDirection.opposite()
} }
argument.type.unwrap().visitType(innerDirection, action) argument.getType().visitType(innerDirection, action)
} }
} }
@@ -20,30 +20,31 @@ import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintS
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.PARTIAL import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.PARTIAL
import org.jetbrains.kotlin.resolve.calls.inference.model.Constraint import org.jetbrains.kotlin.resolve.calls.inference.model.Constraint
import org.jetbrains.kotlin.resolve.calls.inference.model.DeclaredUpperBoundConstraintPosition import org.jetbrains.kotlin.resolve.calls.inference.model.DeclaredUpperBoundConstraintPosition
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraints import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraints
import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtom import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtom
import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.typeUtil.contains import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext
import org.jetbrains.kotlin.types.model.TypeVariableMarker
class VariableFixationFinder( class VariableFixationFinder(
private val trivialConstraintTypeInferenceOracle: TrivialConstraintTypeInferenceOracle private val trivialConstraintTypeInferenceOracle: TrivialConstraintTypeInferenceOracle
) { ) {
interface Context { interface Context : TypeSystemInferenceExtensionContext {
val notFixedTypeVariables: Map<TypeConstructor, VariableWithConstraints> val notFixedTypeVariables: Map<TypeConstructorMarker, VariableWithConstraints>
val postponedTypeVariables: List<NewTypeVariable> val postponedTypeVariables: List<TypeVariableMarker>
} }
data class VariableForFixation( data class VariableForFixation(
val variable: TypeConstructor, val variable: TypeConstructorMarker,
val hasProperConstraint: Boolean, val hasProperConstraint: Boolean,
val hasOnlyTrivialProperConstraint: Boolean = false val hasOnlyTrivialProperConstraint: Boolean = false
) )
fun findFirstVariableForFixation( fun findFirstVariableForFixation(
c: Context, c: Context,
allTypeVariables: List<TypeConstructor>, allTypeVariables: List<TypeConstructorMarker>,
postponedKtPrimitives: List<PostponedResolvedAtom>, postponedKtPrimitives: List<PostponedResolvedAtom>,
completionMode: ConstraintSystemCompletionMode, completionMode: ConstraintSystemCompletionMode,
topLevelType: UnwrappedType topLevelType: UnwrappedType
@@ -59,7 +60,7 @@ class VariableFixationFinder(
} }
private fun Context.getTypeVariableReadiness( private fun Context.getTypeVariableReadiness(
variable: TypeConstructor, variable: TypeConstructorMarker,
dependencyProvider: TypeVariableDependencyInformationProvider dependencyProvider: TypeVariableDependencyInformationProvider
): TypeVariableFixationReadiness = when { ): TypeVariableFixationReadiness = when {
!notFixedTypeVariables.contains(variable) || !notFixedTypeVariables.contains(variable) ||
@@ -72,13 +73,13 @@ class VariableFixationFinder(
} }
private fun Context.findTypeVariableForFixation( private fun Context.findTypeVariableForFixation(
allTypeVariables: List<TypeConstructor>, allTypeVariables: List<TypeConstructorMarker>,
postponedArguments: List<PostponedResolvedAtom>, postponedArguments: List<PostponedResolvedAtom>,
completionMode: ConstraintSystemCompletionMode, completionMode: ConstraintSystemCompletionMode,
topLevelType: UnwrappedType topLevelType: KotlinTypeMarker
): VariableForFixation? { ): VariableForFixation? {
val dependencyProvider = TypeVariableDependencyInformationProvider( val dependencyProvider = TypeVariableDependencyInformationProvider(
notFixedTypeVariables, postponedArguments, topLevelType.takeIf { completionMode == PARTIAL } notFixedTypeVariables, postponedArguments, topLevelType.takeIf { completionMode == PARTIAL }, this
) )
val candidate = allTypeVariables.maxBy { getTypeVariableReadiness(it, dependencyProvider) } ?: return null val candidate = allTypeVariables.maxBy { getTypeVariableReadiness(it, dependencyProvider) } ?: return null
@@ -94,29 +95,29 @@ class VariableFixationFinder(
} }
} }
private fun Context.hasDependencyToOtherTypeVariables(typeVariable: TypeConstructor): Boolean { private fun Context.hasDependencyToOtherTypeVariables(typeVariable: TypeConstructorMarker): Boolean {
for (constraint in notFixedTypeVariables[typeVariable]?.constraints ?: return false) { for (constraint in notFixedTypeVariables[typeVariable]?.constraints ?: return false) {
if (constraint.type.arguments.isNotEmpty() && constraint.type.contains { notFixedTypeVariables.containsKey(it.constructor) }) { if (constraint.type.lowerBoundIfFlexible().argumentsCount() != 0 && constraint.type.contains { notFixedTypeVariables.containsKey(it.typeConstructor()) }) {
return true return true
} }
} }
return false return false
} }
private fun Context.variableHasTrivialOrNonProperConstraints(variable: TypeConstructor): Boolean { private fun Context.variableHasTrivialOrNonProperConstraints(variable: TypeConstructorMarker): Boolean {
return notFixedTypeVariables[variable]?.constraints?.all { constraint -> return notFixedTypeVariables[variable]?.constraints?.all { constraint ->
val isProperConstraint = isProperArgumentConstraint(constraint) val isProperConstraint = isProperArgumentConstraint(constraint)
isProperConstraint && trivialConstraintTypeInferenceOracle.isTrivialConstraint(constraint) || !isProperConstraint isProperConstraint && trivialConstraintTypeInferenceOracle.isTrivialConstraint(constraint) || !isProperConstraint
} ?: false } ?: false
} }
private fun Context.variableHasProperArgumentConstraints(variable: TypeConstructor): Boolean = private fun Context.variableHasProperArgumentConstraints(variable: TypeConstructorMarker): Boolean =
notFixedTypeVariables[variable]?.constraints?.any { isProperArgumentConstraint(it) } ?: false notFixedTypeVariables[variable]?.constraints?.any { isProperArgumentConstraint(it) } ?: false
private fun Context.isProperArgumentConstraint(c: Constraint) = private fun Context.isProperArgumentConstraint(c: Constraint) =
isProperType(c.type) && c.position.initialConstraint.position !is DeclaredUpperBoundConstraintPosition isProperType(c.type) && c.position.initialConstraint.position !is DeclaredUpperBoundConstraintPosition
private fun Context.isProperType(type: UnwrappedType): Boolean = private fun Context.isProperType(type: KotlinTypeMarker): Boolean =
!type.contains { notFixedTypeVariables.containsKey(it.constructor) } !type.contains { notFixedTypeVariables.containsKey(it.typeConstructor()) }
} }
@@ -24,6 +24,8 @@ import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability
import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeVariableMarker
sealed class ConstraintPosition sealed class ConstraintPosition
@@ -48,7 +50,7 @@ class ReceiverConstraintPosition(val argument: KotlinCallArgument) : ConstraintP
override fun toString() = "Receiver $argument" override fun toString() = "Receiver $argument"
} }
class FixVariableConstraintPosition(val variable: NewTypeVariable) : ConstraintPosition() { class FixVariableConstraintPosition(val variable: TypeVariableMarker) : ConstraintPosition() {
override fun toString() = "Fix variable $variable" override fun toString() = "Fix variable $variable"
} }
@@ -88,21 +90,21 @@ abstract class ConstraintSystemCallDiagnostic(applicability: ResolutionCandidate
} }
class NewConstraintError( class NewConstraintError(
val lowerType: UnwrappedType, val lowerType: KotlinTypeMarker,
val upperType: UnwrappedType, val upperType: KotlinTypeMarker,
val position: IncorporationConstraintPosition val position: IncorporationConstraintPosition
) : ConstraintSystemCallDiagnostic(if (position.from is ReceiverConstraintPosition) INAPPLICABLE_WRONG_RECEIVER else INAPPLICABLE) ) : ConstraintSystemCallDiagnostic(if (position.from is ReceiverConstraintPosition) INAPPLICABLE_WRONG_RECEIVER else INAPPLICABLE)
class CapturedTypeFromSubtyping( class CapturedTypeFromSubtyping(
val typeVariable: NewTypeVariable, val typeVariable: TypeVariableMarker,
val constraintType: UnwrappedType, val constraintType: KotlinTypeMarker,
val position: ConstraintPosition val position: ConstraintPosition
) : ConstraintSystemCallDiagnostic(INAPPLICABLE) ) : ConstraintSystemCallDiagnostic(INAPPLICABLE)
class NotEnoughInformationForTypeParameter(val typeVariable: NewTypeVariable) : ConstraintSystemCallDiagnostic(INAPPLICABLE) class NotEnoughInformationForTypeParameter(val typeVariable: TypeVariableMarker) : ConstraintSystemCallDiagnostic(INAPPLICABLE)
class ConstrainingTypeIsError( class ConstrainingTypeIsError(
val typeVariable: NewTypeVariable, val typeVariable: TypeVariableMarker,
val constraintType: UnwrappedType, val constraintType: KotlinTypeMarker,
val position: IncorporationConstraintPosition val position: IncorporationConstraintPosition
) : ConstraintSystemCallDiagnostic(INAPPLICABLE) ) : ConstraintSystemCallDiagnostic(INAPPLICABLE)
@@ -5,13 +5,13 @@
package org.jetbrains.kotlin.resolve.calls.inference.model package org.jetbrains.kotlin.resolve.calls.inference.model
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.substitute
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
import org.jetbrains.kotlin.types.model.TypeVariableMarker
/** /**
* Every type variable can be in the following states: * Every type variable can be in the following states:
@@ -36,24 +36,24 @@ import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
*/ */
interface ConstraintStorage { interface ConstraintStorage {
val allTypeVariables: Map<TypeConstructor, NewTypeVariable> val allTypeVariables: Map<TypeConstructorMarker, TypeVariableMarker>
val notFixedTypeVariables: Map<TypeConstructor, VariableWithConstraints> val notFixedTypeVariables: Map<TypeConstructorMarker, VariableWithConstraints>
val initialConstraints: List<InitialConstraint> val initialConstraints: List<InitialConstraint>
val maxTypeDepthFromInitialConstraints: Int val maxTypeDepthFromInitialConstraints: Int
val errors: List<KotlinCallDiagnostic> val errors: List<KotlinCallDiagnostic>
val hasContradiction: Boolean val hasContradiction: Boolean
val fixedTypeVariables: Map<TypeConstructor, UnwrappedType> val fixedTypeVariables: Map<TypeConstructorMarker, KotlinTypeMarker>
val postponedTypeVariables: List<NewTypeVariable> val postponedTypeVariables: List<TypeVariableMarker>
object Empty : ConstraintStorage { object Empty : ConstraintStorage {
override val allTypeVariables: Map<TypeConstructor, NewTypeVariable> get() = emptyMap() override val allTypeVariables: Map<TypeConstructorMarker, TypeVariableMarker> get() = emptyMap()
override val notFixedTypeVariables: Map<TypeConstructor, VariableWithConstraints> get() = emptyMap() override val notFixedTypeVariables: Map<TypeConstructorMarker, VariableWithConstraints> get() = emptyMap()
override val initialConstraints: List<InitialConstraint> get() = emptyList() override val initialConstraints: List<InitialConstraint> get() = emptyList()
override val maxTypeDepthFromInitialConstraints: Int get() = 1 override val maxTypeDepthFromInitialConstraints: Int get() = 1
override val errors: List<KotlinCallDiagnostic> get() = emptyList() override val errors: List<KotlinCallDiagnostic> get() = emptyList()
override val hasContradiction: Boolean get() = false override val hasContradiction: Boolean get() = false
override val fixedTypeVariables: Map<TypeConstructor, UnwrappedType> get() = emptyMap() override val fixedTypeVariables: Map<TypeConstructorMarker, KotlinTypeMarker> get() = emptyMap()
override val postponedTypeVariables: List<NewTypeVariable> get() = emptyList() override val postponedTypeVariables: List<TypeVariableMarker> get() = emptyList()
} }
} }
@@ -69,7 +69,7 @@ enum class ConstraintKind {
class Constraint( class Constraint(
val kind: ConstraintKind, val kind: ConstraintKind,
val type: UnwrappedType, // flexible types here is allowed val type: KotlinTypeMarker, // flexible types here is allowed
val position: IncorporationConstraintPosition, val position: IncorporationConstraintPosition,
val typeHashCode: Int = type.hashCode() val typeHashCode: Int = type.hashCode()
) { ) {
@@ -93,13 +93,13 @@ class Constraint(
} }
interface VariableWithConstraints { interface VariableWithConstraints {
val typeVariable: NewTypeVariable val typeVariable: TypeVariableMarker
val constraints: List<Constraint> val constraints: List<Constraint>
} }
class InitialConstraint( class InitialConstraint(
val a: UnwrappedType, val a: KotlinTypeMarker,
val b: UnwrappedType, val b: KotlinTypeMarker,
val constraintKind: ConstraintKind, // see [checkConstraint] val constraintKind: ConstraintKind, // see [checkConstraint]
val position: ConstraintPosition val position: ConstraintPosition
) { ) {
@@ -114,13 +114,17 @@ class InitialConstraint(
} }
} }
fun InitialConstraint.checkConstraint(substitutor: TypeSubstitutor): Boolean { //fun InitialConstraint.checkConstraint(substitutor: TypeSubstitutor): Boolean {
val newA = substitutor.substitute(a) // val newA = substitutor.substitute(a)
val newB = substitutor.substitute(a) // val newB = substitutor.substitute(b)
return checkConstraint(newB, constraintKind, newA) // return checkConstraint(newB as KotlinTypeMarker, constraintKind, newA as KotlinTypeMarker)
} //}
fun checkConstraint(constraintType: KotlinTypeMarker, constraintKind: ConstraintKind, resultType: KotlinTypeMarker): Boolean {
require(constraintType is UnwrappedType)
require(resultType is UnwrappedType)
fun checkConstraint(constraintType: UnwrappedType, constraintKind: ConstraintKind, resultType: UnwrappedType): Boolean {
val typeChecker = KotlinTypeChecker.DEFAULT val typeChecker = KotlinTypeChecker.DEFAULT
return when (constraintKind) { return when (constraintKind) {
ConstraintKind.EQUALITY -> typeChecker.equalTypes(constraintType, resultType) ConstraintKind.EQUALITY -> typeChecker.equalTypes(constraintType, resultType)
@@ -11,12 +11,15 @@ import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
import org.jetbrains.kotlin.types.TypeConstructor import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
import org.jetbrains.kotlin.types.model.TypeVariableMarker
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
import kotlin.collections.LinkedHashMap import kotlin.collections.LinkedHashMap
class MutableVariableWithConstraints( class MutableVariableWithConstraints(
override val typeVariable: NewTypeVariable, override val typeVariable: TypeVariableMarker,
constraints: Collection<Constraint> = emptyList() constraints: Collection<Constraint> = emptyList()
) : VariableWithConstraints { ) : VariableWithConstraints {
override val constraints: List<Constraint> override val constraints: List<Constraint>
@@ -89,12 +92,12 @@ class MutableVariableWithConstraints(
internal class MutableConstraintStorage : ConstraintStorage { internal class MutableConstraintStorage : ConstraintStorage {
override val allTypeVariables: MutableMap<TypeConstructor, NewTypeVariable> = LinkedHashMap() override val allTypeVariables: MutableMap<TypeConstructorMarker, TypeVariableMarker> = LinkedHashMap()
override val notFixedTypeVariables: MutableMap<TypeConstructor, MutableVariableWithConstraints> = LinkedHashMap() override val notFixedTypeVariables: MutableMap<TypeConstructorMarker, MutableVariableWithConstraints> = LinkedHashMap()
override val initialConstraints: MutableList<InitialConstraint> = ArrayList() override val initialConstraints: MutableList<InitialConstraint> = ArrayList()
override var maxTypeDepthFromInitialConstraints: Int = 1 override var maxTypeDepthFromInitialConstraints: Int = 1
override val errors: MutableList<KotlinCallDiagnostic> = ArrayList() override val errors: MutableList<KotlinCallDiagnostic> = ArrayList()
override val hasContradiction: Boolean get() = errors.any { !it.candidateApplicability.isSuccess } override val hasContradiction: Boolean get() = errors.any { !it.candidateApplicability.isSuccess }
override val fixedTypeVariables: MutableMap<TypeConstructor, UnwrappedType> = LinkedHashMap() override val fixedTypeVariables: MutableMap<TypeConstructorMarker, KotlinTypeMarker> = LinkedHashMap()
override val postponedTypeVariables: ArrayList<NewTypeVariable> = ArrayList() override val postponedTypeVariables: ArrayList<TypeVariableMarker> = ArrayList()
} }
@@ -6,24 +6,28 @@
package org.jetbrains.kotlin.resolve.calls.inference.model package org.jetbrains.kotlin.resolve.calls.inference.model
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.resolve.calls.components.BuiltInsProvider
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer
import org.jetbrains.kotlin.resolve.calls.inference.* import org.jetbrains.kotlin.resolve.calls.inference.*
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjector import org.jetbrains.kotlin.resolve.calls.inference.components.*
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.components.ResultTypeResolver
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
import org.jetbrains.kotlin.types.StubType import org.jetbrains.kotlin.types.StubType
import org.jetbrains.kotlin.types.TypeConstructor import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.TypeProjectionImpl
import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.typeUtil.contains import org.jetbrains.kotlin.types.checker.ClassicTypeSystemContext
import org.jetbrains.kotlin.types.typeUtil.isUnit import org.jetbrains.kotlin.types.checker.NewCapturedType
import org.jetbrains.kotlin.types.checker.NewCapturedTypeConstructor
import org.jetbrains.kotlin.types.model.*
import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addToStdlib.cast
class NewConstraintSystemImpl( class NewConstraintSystemImpl(
private val constraintInjector: ConstraintInjector, private val constraintInjector: ConstraintInjector,
override val builtIns: KotlinBuiltIns val typeSystemContext: TypeSystemInferenceExtensionContext//,
//override val builtIns: KotlinBuiltIns
) : ) :
TypeSystemInferenceExtensionContext by typeSystemContext,
NewConstraintSystem, NewConstraintSystem,
ConstraintSystemBuilder, ConstraintSystemBuilder,
ConstraintInjector.Context, ConstraintInjector.Context,
@@ -32,7 +36,7 @@ class NewConstraintSystemImpl(
PostponedArgumentsAnalyzer.Context { PostponedArgumentsAnalyzer.Context {
private val storage = MutableConstraintStorage() private val storage = MutableConstraintStorage()
private var state = State.BUILDING private var state = State.BUILDING
private val typeVariablesTransaction: MutableList<NewTypeVariable> = SmartList() private val typeVariablesTransaction: MutableList<TypeVariableMarker> = SmartList()
private enum class State { private enum class State {
BUILDING, BUILDING,
@@ -63,23 +67,23 @@ class NewConstraintSystemImpl(
override fun asPostponedArgumentsAnalyzerContext() = apply { checkState(State.BUILDING) } override fun asPostponedArgumentsAnalyzerContext() = apply { checkState(State.BUILDING) }
// ConstraintSystemOperation // ConstraintSystemOperation
override fun registerVariable(variable: NewTypeVariable) { override fun registerVariable(variable: TypeVariableMarker) {
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
transactionRegisterVariable(variable) transactionRegisterVariable(variable)
storage.allTypeVariables[variable.freshTypeConstructor] = variable storage.allTypeVariables[variable.freshTypeConstructor()] = variable
storage.notFixedTypeVariables[variable.freshTypeConstructor] = MutableVariableWithConstraints(variable) storage.notFixedTypeVariables[variable.freshTypeConstructor()] = MutableVariableWithConstraints(variable)
} }
override fun markPostponedVariable(variable: NewTypeVariable) { override fun markPostponedVariable(variable: TypeVariableMarker) {
storage.postponedTypeVariables += variable storage.postponedTypeVariables += variable
} }
override fun unmarkPostponedVariable(variable: NewTypeVariable) { override fun unmarkPostponedVariable(variable: TypeVariableMarker) {
storage.postponedTypeVariables -= variable storage.postponedTypeVariables -= variable
} }
override fun addSubtypeConstraint(lowerType: UnwrappedType, upperType: UnwrappedType, position: ConstraintPosition) = override fun addSubtypeConstraint(lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker, position: ConstraintPosition) =
constraintInjector.addInitialSubtypeConstraint( constraintInjector.addInitialSubtypeConstraint(
apply { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) }, apply { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) },
lowerType, lowerType,
@@ -87,7 +91,7 @@ class NewConstraintSystemImpl(
position position
) )
override fun addEqualityConstraint(a: UnwrappedType, b: UnwrappedType, position: ConstraintPosition) = override fun addEqualityConstraint(a: KotlinTypeMarker, b: KotlinTypeMarker, position: ConstraintPosition) =
constraintInjector.addInitialEqualityConstraint( constraintInjector.addInitialEqualityConstraint(
apply { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) }, apply { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) },
a, a,
@@ -95,18 +99,18 @@ class NewConstraintSystemImpl(
position position
) )
override fun getProperSuperTypeConstructors(type: UnwrappedType): List<TypeConstructor> { override fun getProperSuperTypeConstructors(type: KotlinTypeMarker): List<TypeConstructorMarker> {
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
val variableWithConstraints = notFixedTypeVariables[type.constructor] ?: return listOf(type.constructor) val variableWithConstraints = notFixedTypeVariables[type.typeConstructor()] ?: return listOf(type.typeConstructor())
return variableWithConstraints.constraints.mapNotNull { return variableWithConstraints.constraints.mapNotNull {
if (it.kind == ConstraintKind.LOWER) return@mapNotNull null if (it.kind == ConstraintKind.LOWER) return@mapNotNull null
it.type.constructor.takeUnless { allTypeVariables.containsKey(it) } it.type.typeConstructor().takeUnless { allTypeVariables.containsKey(it) }
} }
} }
// ConstraintSystemBuilder // ConstraintSystemBuilder
private fun transactionRegisterVariable(variable: NewTypeVariable) { private fun transactionRegisterVariable(variable: TypeVariableMarker) {
if (state != State.TRANSACTION) return if (state != State.TRANSACTION) return
typeVariablesTransaction.add(variable) typeVariablesTransaction.add(variable)
} }
@@ -132,8 +136,8 @@ class NewConstraintSystemImpl(
} }
for (addedTypeVariable in typeVariablesTransaction) { for (addedTypeVariable in typeVariablesTransaction) {
storage.allTypeVariables.remove(addedTypeVariable.freshTypeConstructor) storage.allTypeVariables.remove(addedTypeVariable.freshTypeConstructor())
storage.notFixedTypeVariables.remove(addedTypeVariable.freshTypeConstructor) storage.notFixedTypeVariables.remove(addedTypeVariable.freshTypeConstructor())
} }
storage.maxTypeDepthFromInitialConstraints = beforeMaxTypeDepthFromInitialConstraints storage.maxTypeDepthFromInitialConstraints = beforeMaxTypeDepthFromInitialConstraints
storage.errors.trimToSize(beforeErrorsCount) storage.errors.trimToSize(beforeErrorsCount)
@@ -169,32 +173,32 @@ class NewConstraintSystemImpl(
} }
storage.initialConstraints.addAll(otherSystem.initialConstraints) storage.initialConstraints.addAll(otherSystem.initialConstraints)
storage.maxTypeDepthFromInitialConstraints = storage.maxTypeDepthFromInitialConstraints =
Math.max(storage.maxTypeDepthFromInitialConstraints, otherSystem.maxTypeDepthFromInitialConstraints) Math.max(storage.maxTypeDepthFromInitialConstraints, otherSystem.maxTypeDepthFromInitialConstraints)
storage.errors.addAll(otherSystem.errors) storage.errors.addAll(otherSystem.errors)
storage.fixedTypeVariables.putAll(otherSystem.fixedTypeVariables) storage.fixedTypeVariables.putAll(otherSystem.fixedTypeVariables)
storage.postponedTypeVariables.addAll(otherSystem.postponedTypeVariables) storage.postponedTypeVariables.addAll(otherSystem.postponedTypeVariables)
} }
// ResultTypeResolver.Context, ConstraintSystemBuilder // ResultTypeResolver.Context, ConstraintSystemBuilder
override fun isProperType(type: UnwrappedType): Boolean { override fun isProperType(type: KotlinTypeMarker): Boolean {
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
return !type.contains { return !type.contains {
storage.allTypeVariables.containsKey(it.constructor) storage.allTypeVariables.containsKey(it.typeConstructor())
} }
} }
override fun isTypeVariable(type: UnwrappedType): Boolean { override fun isTypeVariable(type: KotlinTypeMarker): Boolean {
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
return notFixedTypeVariables.containsKey(type.constructor) return notFixedTypeVariables.containsKey(type.typeConstructor())
} }
override fun isPostponedTypeVariable(typeVariable: NewTypeVariable): Boolean { override fun isPostponedTypeVariable(typeVariable: TypeVariableMarker): Boolean {
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
return typeVariable in postponedTypeVariables return typeVariable in postponedTypeVariables
} }
// ConstraintInjector.Context // ConstraintInjector.Context
override val allTypeVariables: Map<TypeConstructor, NewTypeVariable> override val allTypeVariables: Map<TypeConstructorMarker, TypeVariableMarker>
get() { get() {
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
return storage.allTypeVariables return storage.allTypeVariables
@@ -213,19 +217,19 @@ class NewConstraintSystemImpl(
} }
// ConstraintInjector.Context, FixationOrderCalculator.Context // ConstraintInjector.Context, FixationOrderCalculator.Context
override val notFixedTypeVariables: MutableMap<TypeConstructor, MutableVariableWithConstraints> override val notFixedTypeVariables: MutableMap<TypeConstructorMarker, MutableVariableWithConstraints>
get() { get() {
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
return storage.notFixedTypeVariables return storage.notFixedTypeVariables
} }
override val fixedTypeVariables: MutableMap<TypeConstructor, UnwrappedType> override val fixedTypeVariables: MutableMap<TypeConstructorMarker, KotlinTypeMarker>
get() { get() {
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
return storage.fixedTypeVariables return storage.fixedTypeVariables
} }
override val postponedTypeVariables: List<NewTypeVariable> override val postponedTypeVariables: List<TypeVariableMarker>
get() { get() {
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
return storage.postponedTypeVariables return storage.postponedTypeVariables
@@ -238,32 +242,32 @@ class NewConstraintSystemImpl(
} }
// KotlinConstraintSystemCompleter.Context // KotlinConstraintSystemCompleter.Context
override fun fixVariable(variable: NewTypeVariable, resultType: UnwrappedType) { override fun fixVariable(variable: TypeVariableMarker, resultType: KotlinTypeMarker) {
checkState(State.BUILDING, State.COMPLETION) checkState(State.BUILDING, State.COMPLETION)
constraintInjector.addInitialEqualityConstraint(this, variable.defaultType, resultType, FixVariableConstraintPosition(variable)) constraintInjector.addInitialEqualityConstraint(this, variable.defaultType(), resultType, FixVariableConstraintPosition(variable))
notFixedTypeVariables.remove(variable.freshTypeConstructor) notFixedTypeVariables.remove(variable.freshTypeConstructor())
for (variableWithConstraint in notFixedTypeVariables.values) { for (variableWithConstraint in notFixedTypeVariables.values) {
variableWithConstraint.removeConstrains { variableWithConstraint.removeConstrains {
it.type.contains { it.constructor == variable.freshTypeConstructor } it.type.contains { it.typeConstructor() == variable.freshTypeConstructor() }
} }
} }
storage.fixedTypeVariables[variable.freshTypeConstructor] = resultType storage.fixedTypeVariables[variable.freshTypeConstructor()] = resultType
} }
// KotlinConstraintSystemCompleter.Context, PostponedArgumentsAnalyzer.Context // KotlinConstraintSystemCompleter.Context, PostponedArgumentsAnalyzer.Context
override fun canBeProper(type: UnwrappedType): Boolean { override fun canBeProper(type: KotlinTypeMarker): Boolean {
checkState(State.BUILDING, State.COMPLETION) checkState(State.BUILDING, State.COMPLETION)
return !type.contains { storage.notFixedTypeVariables.containsKey(it.constructor) } return !type.contains { storage.notFixedTypeVariables.containsKey(it.typeConstructor()) }
} }
override fun containsOnlyFixedOrPostponedVariables(type: UnwrappedType): Boolean { override fun containsOnlyFixedOrPostponedVariables(type: KotlinTypeMarker): Boolean {
checkState(State.BUILDING, State.COMPLETION) checkState(State.BUILDING, State.COMPLETION)
return !type.contains { return !type.contains {
val variable = storage.notFixedTypeVariables[it.constructor]?.typeVariable val variable = storage.notFixedTypeVariables[it.typeConstructor()]?.typeVariable
variable !in storage.postponedTypeVariables && storage.notFixedTypeVariables.containsKey(it.constructor) variable !in storage.postponedTypeVariables && storage.notFixedTypeVariables.containsKey(it.typeConstructor())
} }
} }
@@ -273,14 +277,15 @@ class NewConstraintSystemImpl(
return buildCurrentSubstitutor(emptyMap()) return buildCurrentSubstitutor(emptyMap())
} }
override fun buildCurrentSubstitutor(additionalBindings: Map<TypeConstructor, StubType>): NewTypeSubstitutor { override fun buildCurrentSubstitutor(additionalBindings: Map<TypeConstructorMarker, StubTypeMarker>): NewTypeSubstitutor {
checkState(State.BUILDING, State.COMPLETION) checkState(State.BUILDING, State.COMPLETION)
return storage.buildCurrentSubstitutor(additionalBindings) return storage.buildCurrentSubstitutor(additionalBindings)
} }
override fun bindingStubsForPostponedVariables(): Map<NewTypeVariable, StubType> { override fun bindingStubsForPostponedVariables(): Map<TypeVariableMarker, StubTypeMarker> {
checkState(State.BUILDING, State.COMPLETION) checkState(State.BUILDING, State.COMPLETION)
return storage.postponedTypeVariables.associate { it to StubType(it.freshTypeConstructor, it.defaultType.isMarkedNullable) } // TODO: SUB
return storage.postponedTypeVariables.associate { it to createStubType(it)/*StubType(it.freshTypeConstructor() as TypeConstructor, it.defaultType().isMarkedNullable())*/ }
} }
override fun currentStorage(): ConstraintStorage { override fun currentStorage(): ConstraintStorage {
@@ -289,10 +294,10 @@ class NewConstraintSystemImpl(
} }
// PostponedArgumentsAnalyzer.Context // PostponedArgumentsAnalyzer.Context
override fun hasUpperOrEqualUnitConstraint(type: UnwrappedType): Boolean { override fun hasUpperOrEqualUnitConstraint(type: KotlinTypeMarker): Boolean {
checkState(State.BUILDING, State.COMPLETION, State.FREEZED) checkState(State.BUILDING, State.COMPLETION, State.FREEZED)
val constraints = storage.notFixedTypeVariables[type.constructor]?.constraints ?: return false val constraints = storage.notFixedTypeVariables[type.typeConstructor()]?.constraints ?: return false
return constraints.any { (it.kind == ConstraintKind.UPPER || it.kind == ConstraintKind.EQUALITY) && it.type.isUnit() } return constraints.any { (it.kind == ConstraintKind.UPPER || it.kind == ConstraintKind.EQUALITY) && it.type.isUnit() }
} }
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.types.KotlinTypeFactory
import org.jetbrains.kotlin.types.SimpleType import org.jetbrains.kotlin.types.SimpleType
import org.jetbrains.kotlin.types.TypeConstructor import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.checker.NewTypeVariableConstructor import org.jetbrains.kotlin.types.checker.NewTypeVariableConstructor
import org.jetbrains.kotlin.types.model.TypeVariableMarker
class TypeVariableTypeConstructor(private val builtIns: KotlinBuiltIns, val debugName: String) : TypeConstructor, class TypeVariableTypeConstructor(private val builtIns: KotlinBuiltIns, val debugName: String) : TypeConstructor,
@@ -42,7 +43,7 @@ class TypeVariableTypeConstructor(private val builtIns: KotlinBuiltIns, val debu
override fun toString() = "TypeVariable($debugName)" override fun toString() = "TypeVariable($debugName)"
} }
sealed class NewTypeVariable(builtIns: KotlinBuiltIns, name: String) { sealed class NewTypeVariable(builtIns: KotlinBuiltIns, name: String) : TypeVariableMarker {
val freshTypeConstructor: TypeConstructor = TypeVariableTypeConstructor(builtIns, name) val freshTypeConstructor: TypeConstructor = TypeVariableTypeConstructor(builtIns, name)
// member scope is used if we have receiver with type TypeVariable(T) // member scope is used if we have receiver with type TypeVariable(T)
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.calls.model
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.resolve.calls.components.NewConstraintSystemImpl
import org.jetbrains.kotlin.resolve.calls.components.TypeArgumentsToParametersMapper import org.jetbrains.kotlin.resolve.calls.components.TypeArgumentsToParametersMapper
import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem
import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor
@@ -27,7 +28,6 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImp
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.tower.* import org.jetbrains.kotlin.resolve.calls.tower.*
import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.UnwrappedType
abstract class ResolutionPart { abstract class ResolutionPart {
@@ -23,10 +23,7 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.getReceiverValueWithSmartCa
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForTypeAliasObject import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForTypeAliasObject
import org.jetbrains.kotlin.resolve.calls.util.isLowPriorityFromStdlibJre7Or8 import org.jetbrains.kotlin.resolve.calls.util.isLowPriorityFromStdlibJre7Or8
import org.jetbrains.kotlin.resolve.descriptorUtil.HIDES_MEMBERS_NAME_LIST import org.jetbrains.kotlin.resolve.descriptorUtil.*
import org.jetbrains.kotlin.resolve.descriptorUtil.hasClassValueDescriptor
import org.jetbrains.kotlin.resolve.descriptorUtil.hasHidesMembersAnnotation
import org.jetbrains.kotlin.resolve.descriptorUtil.hasLowPriorityInOverloadResolution
import org.jetbrains.kotlin.resolve.scopes.* import org.jetbrains.kotlin.resolve.scopes.*
import org.jetbrains.kotlin.resolve.scopes.receivers.CastImplicitClassReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.CastImplicitClassReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
@@ -135,7 +132,7 @@ internal class MemberScopeTowerLevel(
private fun CallableDescriptor.approximateCapturedTypes(): CallableDescriptor { private fun CallableDescriptor.approximateCapturedTypes(): CallableDescriptor {
if (!isNewInferenceEnabled) return this if (!isNewInferenceEnabled) return this
val approximator = TypeApproximator() val approximator = TypeApproximator(builtIns)
val wrappedSubstitution = object : TypeSubstitution() { val wrappedSubstitution = object : TypeSubstitution() {
override fun get(key: KotlinType): TypeProjection? = null override fun get(key: KotlinType): TypeProjection? = null
override fun prepareTopLevelType(topLevelType: KotlinType, position: Variance) = when (position) { override fun prepareTopLevelType(topLevelType: KotlinType, position: Variance) = when (position) {
@@ -16,19 +16,19 @@
package org.jetbrains.kotlin.types package org.jetbrains.kotlin.types
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator
import org.jetbrains.kotlin.resolve.calls.components.ClassicTypeSystemContextForCS
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableTypeConstructor import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableTypeConstructor
import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration.IntersectionStrategy.* import org.jetbrains.kotlin.types.TypeApproximatorConfiguration.IntersectionStrategy.*
import org.jetbrains.kotlin.types.checker.* import org.jetbrains.kotlin.types.checker.NewCapturedType
import org.jetbrains.kotlin.types.model.CaptureStatus import org.jetbrains.kotlin.types.checker.NewCapturedTypeConstructor
import org.jetbrains.kotlin.types.model.*
import org.jetbrains.kotlin.types.model.CaptureStatus.* import org.jetbrains.kotlin.types.model.CaptureStatus.*
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
import org.jetbrains.kotlin.types.typeUtil.builtIns import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.types.typeUtil.isNothing
import org.jetbrains.kotlin.types.typeUtil.isNullableAny
open class TypeApproximatorConfiguration { open class TypeApproximatorConfiguration {
@@ -89,10 +89,8 @@ open class TypeApproximatorConfiguration {
} }
} }
class TypeApproximator {
private val referenceApproximateToSuperType = this::approximateSimpleToSuperType
private val referenceApproximateToSubType = this::approximateSimpleToSubType
class TypeApproximator(builtIns: KotlinBuiltIns) : AbstractTypeApproximator(ClassicTypeSystemContextForCS(builtIns)) {
fun approximateDeclarationType(baseType: KotlinType, local: Boolean, languageVersionSettings: LanguageVersionSettings): UnwrappedType { fun approximateDeclarationType(baseType: KotlinType, local: Boolean, languageVersionSettings: LanguageVersionSettings): UnwrappedType {
if (!languageVersionSettings.supportsFeature(LanguageFeature.NewInference)) return baseType.unwrap() if (!languageVersionSettings.supportsFeature(LanguageFeature.NewInference)) return baseType.unwrap()
@@ -103,49 +101,68 @@ class TypeApproximator {
// null means that this input type is the result, i.e. input type not contains not-allowed kind of types // null means that this input type is the result, i.e. input type not contains not-allowed kind of types
// type <: resultType // type <: resultType
fun approximateToSuperType(type: UnwrappedType, conf: TypeApproximatorConfiguration): UnwrappedType? = fun approximateToSuperType(type: UnwrappedType, conf: TypeApproximatorConfiguration): UnwrappedType? =
approximateToSuperType(type, conf, -type.typeDepth()) super.approximateToSuperType(type, conf) as UnwrappedType?
// resultType <: type // resultType <: type
fun approximateToSubType(type: UnwrappedType, conf: TypeApproximatorConfiguration): UnwrappedType? = fun approximateToSubType(type: UnwrappedType, conf: TypeApproximatorConfiguration): UnwrappedType? =
super.approximateToSubType(type, conf) as UnwrappedType?
}
abstract class AbstractTypeApproximator(val ctx: TypeSystemInferenceExtensionContext) : TypeSystemInferenceExtensionContext by ctx {
private val referenceApproximateToSuperType = this::approximateSimpleToSuperType
private val referenceApproximateToSubType = this::approximateSimpleToSubType
// null means that this input type is the result, i.e. input type not contains not-allowed kind of types
// type <: resultType
fun approximateToSuperType(type: KotlinTypeMarker, conf: TypeApproximatorConfiguration): KotlinTypeMarker? =
approximateToSuperType(type, conf, -type.typeDepth())
// resultType <: type
fun approximateToSubType(type: KotlinTypeMarker, conf: TypeApproximatorConfiguration): KotlinTypeMarker? =
approximateToSubType(type, conf, -type.typeDepth()) approximateToSubType(type, conf, -type.typeDepth())
private fun approximateToSuperType(type: UnwrappedType, conf: TypeApproximatorConfiguration, depth: Int): UnwrappedType? { private fun approximateToSuperType(type: KotlinTypeMarker, conf: TypeApproximatorConfiguration, depth: Int): KotlinTypeMarker? {
if (type is TypeUtils.SpecialType) return null if (type is TypeUtils.SpecialType) return null
return approximateTo( return approximateTo(
NewKotlinTypeChecker.transformToNewType(type), conf, FlexibleType::upperBound, prepareType(type), conf, { upperBound() },
referenceApproximateToSuperType, depth referenceApproximateToSuperType, depth
) )
} }
private fun approximateToSubType(type: UnwrappedType, conf: TypeApproximatorConfiguration, depth: Int): UnwrappedType? { private fun approximateToSubType(type: KotlinTypeMarker, conf: TypeApproximatorConfiguration, depth: Int): KotlinTypeMarker? {
if (type is TypeUtils.SpecialType) return null if (type is TypeUtils.SpecialType) return null
return approximateTo( return approximateTo(
NewKotlinTypeChecker.transformToNewType(type), conf, FlexibleType::lowerBound, prepareType(type), conf, { lowerBound() },
referenceApproximateToSubType, depth referenceApproximateToSubType, depth
) )
} }
// comments for case bound = upperBound, approximateTo = toSuperType // comments for case bound = upperBound, approximateTo = toSuperType
private fun approximateTo( private fun approximateTo(
type: UnwrappedType, type: KotlinTypeMarker,
conf: TypeApproximatorConfiguration, conf: TypeApproximatorConfiguration,
bound: FlexibleType.() -> SimpleType, bound: FlexibleTypeMarker.() -> SimpleTypeMarker,
approximateTo: (SimpleType, TypeApproximatorConfiguration, depth: Int) -> UnwrappedType?, approximateTo: (SimpleTypeMarker, TypeApproximatorConfiguration, depth: Int) -> KotlinTypeMarker?,
depth: Int depth: Int
): UnwrappedType? { ): KotlinTypeMarker? {
when (type) { when (type) {
is SimpleType -> return approximateTo(type, conf, depth) is SimpleTypeMarker -> return approximateTo(type, conf, depth)
is FlexibleType -> { is FlexibleTypeMarker -> {
if (type is DynamicType) { if (type.isDynamic()) {
return if (conf.dynamic) null else type.bound() return if (conf.dynamic) null else type.bound()
} else if (type is RawType) { } else if (type.asRawType() != null) {
return if (conf.rawType) null else type.bound() return if (conf.rawType) null else type.bound()
} }
// TODO: currently we can lose information about enhancement, should be fixed later // TODO: Restore check
assert(type is FlexibleTypeImpl || type is FlexibleTypeWithEnhancement) { // // TODO: currently we can lose information about enhancement, should be fixed later
"Unexpected subclass of FlexibleType: ${type::class.java.canonicalName}, type = $type" // assert(type is FlexibleTypeImpl || type is FlexibleTypeWithEnhancement) {
} // "Unexpected subclass of FlexibleType: ${type::class.java.canonicalName}, type = $type"
// }
if (conf.flexible) { if (conf.flexible) {
/** /**
@@ -158,8 +175,8 @@ class TypeApproximator {
* I.e. for every type B such as L_2 <: B, L_1 <: B. For example B = L_2. * I.e. for every type B such as L_2 <: B, L_1 <: B. For example B = L_2.
*/ */
val lowerResult = approximateTo(type.lowerBound, conf, depth) val lowerResult = approximateTo(type.lowerBound(), conf, depth)
val upperResult = approximateTo(type.upperBound, conf, depth) val upperResult = approximateTo(type.upperBound(), conf, depth)
if (lowerResult == null && upperResult == null) return null if (lowerResult == null && upperResult == null) return null
/** /**
@@ -169,38 +186,39 @@ class TypeApproximator {
* *
* If U_1 <: U_2.lower .. U_2.upper, then we know only that U_1 <: U_2.upper. * If U_1 <: U_2.lower .. U_2.upper, then we know only that U_1 <: U_2.upper.
*/ */
return KotlinTypeFactory.flexibleType( return createFlexibleType(
lowerResult?.lowerIfFlexible() ?: type.lowerBound, lowerResult?.lowerBoundIfFlexible() ?: type.lowerBound(),
upperResult?.upperIfFlexible() ?: type.upperBound upperResult?.upperBoundIfFlexible() ?: type.upperBound()
) )
} else { } else {
return type.bound().let { approximateTo(it, conf, depth) ?: it } return type.bound().let { approximateTo(it, conf, depth) ?: it }
} }
} }
else -> error("sealed")
} }
} }
private fun approximateIntersectionType( private fun approximateIntersectionType(
type: SimpleType, type: SimpleTypeMarker,
conf: TypeApproximatorConfiguration, conf: TypeApproximatorConfiguration,
toSuper: Boolean, toSuper: Boolean,
depth: Int depth: Int
): UnwrappedType? { ): KotlinTypeMarker? {
val typeConstructor = type.constructor val typeConstructor = type.typeConstructor()
assert(typeConstructor is IntersectionTypeConstructor) { assert(typeConstructor.isIntersection()) {
"Should be intersection type: $type, typeConstructor class: ${typeConstructor::class.java.canonicalName}" "Should be intersection type: $type, typeConstructor class: ${typeConstructor::class.java.canonicalName}"
} }
assert(typeConstructor.supertypes.isNotEmpty()) { assert(typeConstructor.supertypes().isNotEmpty()) {
"Supertypes for intersection type should not be empty: $type" "Supertypes for intersection type should not be empty: $type"
} }
var thereIsApproximation = false var thereIsApproximation = false
val newTypes = typeConstructor.supertypes.map { val newTypes = typeConstructor.supertypes().map {
val newType = if (toSuper) approximateToSuperType(it.unwrap(), conf, depth) else approximateToSubType(it.unwrap(), conf, depth) val newType = if (toSuper) approximateToSuperType(it, conf, depth) else approximateToSubType(it, conf, depth)
if (newType != null) { if (newType != null) {
thereIsApproximation = true thereIsApproximation = true
newType newType
} else it.unwrap() } else it
} }
/** /**
@@ -215,12 +233,12 @@ class TypeApproximator {
// commonSupertypeCalculator should handle flexible types correctly // commonSupertypeCalculator should handle flexible types correctly
TO_COMMON_SUPERTYPE -> { TO_COMMON_SUPERTYPE -> {
if (!toSuper) return type.defaultResult(toSuper = false) if (!toSuper) return type.defaultResult(toSuper = false)
val resultType = NewCommonSuperTypeCalculator.commonSuperType(newTypes) val resultType = with(NewCommonSuperTypeCalculator) { commonSuperType(newTypes) }
approximateToSuperType(resultType.unwrap(), conf) ?: resultType.unwrap() approximateToSuperType(resultType, conf) ?: resultType
} }
} }
return if (type.isMarkedNullable) baseResult.makeNullableAsSpecified(true) else baseResult return if (type.isMarkedNullable()) baseResult.withNullability(true) else baseResult
} }
private fun approximateCapturedType( private fun approximateCapturedType(
@@ -228,30 +246,30 @@ class TypeApproximator {
conf: TypeApproximatorConfiguration, conf: TypeApproximatorConfiguration,
toSuper: Boolean, toSuper: Boolean,
depth: Int depth: Int
): UnwrappedType? { ): KotlinTypeMarker? {
val supertypes = type.constructor.supertypes val supertypes = type.typeConstructor().supertypes()
val baseSuperType = when (supertypes.size) { val baseSuperType = when (supertypes.size) {
0 -> type.builtIns.nullableAnyType // Let C = in Int, then superType for C and C? is Any? 0 -> type.builtIns.nullableAnyType // Let C = in Int, then superType for C and C? is Any?
1 -> supertypes.single() 1 -> supertypes.single()
// Consider the following example: // Consider the following example:
// A.getA()::class.java, where `getA()` returns some class from Java // A.getA()::class.java, where `getA()` returns some class from Java
// From `::class` we are getting type KClass<Cap<out A!>>, where Cap<out A!> have two supertypes: // From `::class` we are getting type KClass<Cap<out A!>>, where Cap<out A!> have two supertypes:
// - Any (from declared upper bound of type parameter for KClass) // - Any (from declared upper bound of type parameter for KClass)
// - (A..A?) -- from A!, projection type of captured type // - (A..A?) -- from A!, projection type of captured type
// Now, after approximation we were getting type `KClass<out A>`, because { Any & (A..A?) } = A, // Now, after approximation we were getting type `KClass<out A>`, because { Any & (A..A?) } = A,
// but in old inference type was equal to `KClass<out A!>`. // but in old inference type was equal to `KClass<out A!>`.
// Important note that from the point of type system first type is more specific: // Important note that from the point of type system first type is more specific:
// Here, approximation of KClass<Cap<out A!>> is a type KClass<T> such that KClass<Cap<out A!>> <: KClass<out T> => // Here, approximation of KClass<Cap<out A!>> is a type KClass<T> such that KClass<Cap<out A!>> <: KClass<out T> =>
// So, the the more specific type for T would be "some non-null (because of declared upper bound type) subtype of A", which is `out A` // So, the the more specific type for T would be "some non-null (because of declared upper bound type) subtype of A", which is `out A`
// But for now, to reduce differences in behaviour of old and new inference, we'll approximate such types to `KClass<out A!>` // But for now, to reduce differences in behaviour of old and new inference, we'll approximate such types to `KClass<out A!>`
// Once NI will be more stabilized, we'll use more specific type // Once NI will be more stabilized, we'll use more specific type
else -> type.constructor.projection.type.unwrap() else -> type.typeConstructorProjection().getType()//.unwrap()
} }
val baseSubType = type.lowerType ?: type.builtIns.nothingType val baseSubType = type.lowerType ?: type.builtIns.nothingType
@@ -276,32 +294,38 @@ class TypeApproximator {
// C = in Int, Int <: C => Int? <: C? // C = in Int, Int <: C => Int? <: C?
// C = out Number, C <: Number => C? <: Number? // C = out Number, C <: Number => C? <: Number?
return if (type.isMarkedNullable) baseResult.makeNullableAsSpecified(true) else baseResult return if (type.isMarkedNullable) baseResult.withNullability(true) else baseResult
} }
private fun approximateSimpleToSuperType(type: SimpleType, conf: TypeApproximatorConfiguration, depth: Int) = private fun approximateSimpleToSuperType(type: SimpleTypeMarker, conf: TypeApproximatorConfiguration, depth: Int) =
approximateTo(type, conf, toSuper = true, depth = depth) approximateTo(type, conf, toSuper = true, depth = depth)
private fun approximateSimpleToSubType(type: SimpleType, conf: TypeApproximatorConfiguration, depth: Int) = private fun approximateSimpleToSubType(type: SimpleTypeMarker, conf: TypeApproximatorConfiguration, depth: Int) =
approximateTo(type, conf, toSuper = false, depth = depth) approximateTo(type, conf, toSuper = false, depth = depth)
private fun approximateTo(type: SimpleType, conf: TypeApproximatorConfiguration, toSuper: Boolean, depth: Int): UnwrappedType? { private fun approximateTo(
if (type.isError) { type: SimpleTypeMarker,
conf: TypeApproximatorConfiguration,
toSuper: Boolean,
depth: Int
): KotlinTypeMarker? {
if (type.isError()) {
// todo -- fix builtIns. Now builtIns here is DefaultBuiltIns // todo -- fix builtIns. Now builtIns here is DefaultBuiltIns
return if (conf.errorType) null else type.defaultResult(toSuper) return if (conf.errorType) null else type.defaultResult(toSuper)
} }
if (depth > 3) return type.defaultResult(toSuper) if (depth > 3) return type.defaultResult(toSuper)
if (type.arguments.isNotEmpty()) { if (type.argumentsCount() != 0) {
return approximateParametrizedType(type, conf, toSuper, depth + 1) return approximateParametrizedType(type, conf, toSuper, depth + 1)
} }
if (type is DefinitelyNotNullType) { val definitelyNotNullType = type.asDefinitelyNotNullType()
return approximateDefinitelyNotNullType(type, conf, toSuper, depth) if (definitelyNotNullType != null) {
return approximateDefinitelyNotNullType(definitelyNotNullType, conf, toSuper, depth)
} }
val typeConstructor = type.constructor val typeConstructor = type.typeConstructor()
if (typeConstructor is NewCapturedTypeConstructor) { if (typeConstructor is NewCapturedTypeConstructor) {
assert(type is NewCapturedType) { assert(type is NewCapturedType) {
@@ -312,7 +336,7 @@ class TypeApproximator {
return approximateCapturedType(type as NewCapturedType, conf, toSuper, depth) return approximateCapturedType(type as NewCapturedType, conf, toSuper, depth)
} }
if (typeConstructor is IntersectionTypeConstructor) { if (typeConstructor.isIntersection()) {
return approximateIntersectionType(type, conf, toSuper, depth) return approximateIntersectionType(type, conf, toSuper, depth)
} }
@@ -320,9 +344,9 @@ class TypeApproximator {
return if (conf.typeVariable(typeConstructor)) null else type.defaultResult(toSuper) return if (conf.typeVariable(typeConstructor)) null else type.defaultResult(toSuper)
} }
if (typeConstructor is IntegerLiteralTypeConstructor) { if (typeConstructor.isIntegerLiteralTypeConstructor()) {
return if (conf.integerLiteralType) return if (conf.integerLiteralType)
typeConstructor.getApproximatedType().unwrap().makeNullableAsSpecified(type.isMarkedNullable) typeConstructor.getApproximatedIntegerLiteralType().withNullability(type.isMarkedNullable())
else else
null null
} }
@@ -331,63 +355,64 @@ class TypeApproximator {
} }
private fun approximateDefinitelyNotNullType( private fun approximateDefinitelyNotNullType(
type: DefinitelyNotNullType, type: DefinitelyNotNullTypeMarker,
conf: TypeApproximatorConfiguration, conf: TypeApproximatorConfiguration,
toSuper: Boolean, toSuper: Boolean,
depth: Int depth: Int
): UnwrappedType? { ): KotlinTypeMarker? {
val approximatedOriginalType = approximateTo(type.original, conf, toSuper, depth) val approximatedOriginalType = approximateTo(type.original(), conf, toSuper, depth)
return if (conf.definitelyNotNullType) { return if (conf.definitelyNotNullType) {
approximatedOriginalType?.makeDefinitelyNotNullOrNotNull() approximatedOriginalType?.makeDefinitelyNotNullOrNotNull()
} else { } else {
if (toSuper) if (toSuper)
(approximatedOriginalType ?: type.original).makeNullableAsSpecified(false) (approximatedOriginalType ?: type.original()).withNullability(false)
else else
type.defaultResult(toSuper) type.defaultResult(toSuper)
} }
} }
private fun isApproximateDirectionToSuper(effectiveVariance: Variance, toSuper: Boolean) = private fun isApproximateDirectionToSuper(effectiveVariance: TypeVariance, toSuper: Boolean) =
when (effectiveVariance) { when (effectiveVariance) {
Variance.OUT_VARIANCE -> toSuper TypeVariance.OUT -> toSuper
Variance.IN_VARIANCE -> !toSuper TypeVariance.IN -> !toSuper
Variance.INVARIANT -> throw AssertionError("Incorrect variance $effectiveVariance") TypeVariance.INV -> throw AssertionError("Incorrect variance $effectiveVariance")
} }
private fun approximateParametrizedType( private fun approximateParametrizedType(
type: SimpleType, type: SimpleTypeMarker,
conf: TypeApproximatorConfiguration, conf: TypeApproximatorConfiguration,
toSuper: Boolean, toSuper: Boolean,
depth: Int depth: Int
): SimpleType? { ): SimpleTypeMarker? {
val parameters = type.constructor.parameters val typeConstructor = type.typeConstructor()
val arguments = type.arguments // val parameters = type.typeConstructor().parameters
if (parameters.size != arguments.size) { // val arguments = type.arguments
if (typeConstructor.parametersCount() != type.argumentsCount()) {
return if (conf.errorType) { return if (conf.errorType) {
ErrorUtils.createErrorType("Inconsistent type: $type (parameters.size = ${parameters.size}, arguments.size = ${arguments.size})") ErrorUtils.createErrorType("Inconsistent type: $type (parameters.size = ${typeConstructor.parametersCount()}, arguments.size = ${type.argumentsCount()})")
} else type.defaultResult(toSuper) } else type.defaultResult(toSuper)
} }
val newArguments = arrayOfNulls<TypeProjection?>(arguments.size) val newArguments = arrayOfNulls<TypeArgumentMarker?>(type.argumentsCount())
loop@ for (index in arguments.indices) { loop@ for (index in 0 until type.argumentsCount()) {
val parameter = parameters[index] val parameter = typeConstructor.getParameter(index)
val argument = arguments[index] val argument = type.getArgument(index)
if (argument.isStarProjection) continue if (argument.isStarProjection()) continue
val argumentType = argument.type.unwrap() val argumentType = argument.getType()//.unwrap()
val effectiveVariance = NewKotlinTypeChecker.effectiveVariance(parameter.variance, argument.projectionKind) val effectiveVariance = AbstractTypeChecker.effectiveVariance(parameter.getVariance(), argument.getVariance())
when (effectiveVariance) { when (effectiveVariance) {
null -> { null -> {
return if (conf.errorType) { return if (conf.errorType) {
ErrorUtils.createErrorType( ErrorUtils.createErrorType(
"Inconsistent type: $type ($index parameter has declared variance: ${parameter.variance}, " + "Inconsistent type: $type ($index parameter has declared variance: ${parameter.getVariance()}, " +
"but argument variance is ${argument.projectionKind})" "but argument variance is ${argument.getVariance()})"
) )
} else type.defaultResult(toSuper) } else type.defaultResult(toSuper)
} }
Variance.OUT_VARIANCE, Variance.IN_VARIANCE -> { TypeVariance.OUT, TypeVariance.IN -> {
/** /**
* Out<Foo> <: Out<superType(Foo)> * Out<Foo> <: Out<superType(Foo)>
* Inv<out Foo> <: Inv<out superType(Foo)> * Inv<out Foo> <: Inv<out superType(Foo)>
@@ -403,22 +428,27 @@ class TypeApproximator {
} }
} ?: continue@loop } ?: continue@loop
if (parameter.variance == Variance.INVARIANT) { if (parameter.getVariance() == TypeVariance.INV) {
newArguments[index] = TypeProjectionImpl(effectiveVariance, approximatedArgument) newArguments[index] = createTypeArgument(approximatedArgument, effectiveVariance)
} else { } else {
newArguments[index] = approximatedArgument.asTypeProjection() newArguments[index] = approximatedArgument.asTypeArgument()
} }
} }
Variance.INVARIANT -> { TypeVariance.INV -> {
if (!toSuper) { if (!toSuper) {
// Inv<Foo> cannot be approximated to subType // Inv<Foo> cannot be approximated to subType
val toSubType = approximateToSubType(argumentType, conf, depth) ?: continue@loop val toSubType = approximateToSubType(argumentType, conf, depth) ?: continue@loop
// Inv<Foo!> is supertype for Inv<Foo?> // Inv<Foo!> is supertype for Inv<Foo?>
if (!NewKotlinTypeChecker.equalTypes(argumentType, toSubType)) return type.defaultResult(toSuper) if (!AbstractTypeChecker.equalTypes(
this,
argumentType,
toSubType
)
) return type.defaultResult(toSuper)
// also Captured(out Nothing) = Nothing // also Captured(out Nothing) = Nothing
newArguments[index] = toSubType.asTypeProjection() newArguments[index] = toSubType.asTypeArgument()
continue@loop continue@loop
} }
@@ -433,10 +463,10 @@ class TypeApproximator {
* Note that for case Inv<C> we will chose Inv<in Int>, because it is more informative then Inv<out Any?>. * Note that for case Inv<C> we will chose Inv<in Int>, because it is more informative then Inv<out Any?>.
* May be we should do the same for deeper types, but not now. * May be we should do the same for deeper types, but not now.
*/ */
if (argumentType.constructor is NewCapturedTypeConstructor) { if (argumentType.typeConstructor() is NewCapturedTypeConstructor) {
val subType = approximateToSubType(argumentType, conf, depth) ?: continue@loop val subType = approximateToSubType(argumentType, conf, depth) ?: continue@loop
if (!subType.isTrivialSub()) { if (!subType.isTrivialSub()) {
newArguments[index] = TypeProjectionImpl(Variance.IN_VARIANCE, subType) newArguments[index] = createTypeArgument(subType, TypeVariance.IN)
continue@loop continue@loop
} }
} }
@@ -447,15 +477,15 @@ class TypeApproximator {
val approximatedSubType = val approximatedSubType =
approximateToSubType(argumentType, conf, depth) ?: continue@loop // seems like this is never null approximateToSubType(argumentType, conf, depth) ?: continue@loop // seems like this is never null
if (!approximatedSubType.isTrivialSub()) { if (!approximatedSubType.isTrivialSub()) {
newArguments[index] = TypeProjectionImpl(Variance.IN_VARIANCE, approximatedSubType) newArguments[index] = createTypeArgument(approximatedSubType, TypeVariance.IN)
continue@loop continue@loop
} }
} }
if (NewKotlinTypeChecker.equalTypes(argumentType, approximatedSuperType)) { if (AbstractTypeChecker.equalTypes(this, argumentType, approximatedSuperType)) {
newArguments[index] = approximatedSuperType.asTypeProjection() newArguments[index] = approximatedSuperType.asTypeArgument()
} else { } else {
newArguments[index] = TypeProjectionImpl(Variance.OUT_VARIANCE, approximatedSuperType) newArguments[index] = createTypeArgument(approximatedSuperType, TypeVariance.OUT)
} }
} }
} }
@@ -463,33 +493,33 @@ class TypeApproximator {
if (newArguments.all { it == null }) return null if (newArguments.all { it == null }) return null
val newArgumentsList = arguments.mapIndexed { index, oldArgument -> newArguments[index] ?: oldArgument } val newArgumentsList = List(type.argumentsCount()) { index -> newArguments[index] ?: type.getArgument(index) }
return type.replace(newArgumentsList) return type.replaceArguments(newArgumentsList)
} }
private fun SimpleType.defaultResult(toSuper: Boolean) = if (toSuper) builtIns.nullableAnyType else { private fun SimpleTypeMarker.defaultResult(toSuper: Boolean) = if (toSuper) nullableAnyType() else {
if (isMarkedNullable) builtIns.nullableNothingType else builtIns.nothingType if (isMarkedNullable()) nullableNothingType() else nothingType()
} }
// Any? or Any! // Any? or Any!
private fun UnwrappedType.isTrivialSuper() = upperIfFlexible().isNullableAny() private fun KotlinTypeMarker.isTrivialSuper() = upperBoundIfFlexible().isNullableAny()
// Nothing or Nothing! // Nothing or Nothing!
private fun UnwrappedType.isTrivialSub() = lowerIfFlexible().isNothing() private fun KotlinTypeMarker.isTrivialSub() = lowerBoundIfFlexible().isNothing()
}
internal fun UnwrappedType.typeDepth() =
when (this) {
is SimpleType -> typeDepth()
is FlexibleType -> Math.max(lowerBound.typeDepth(), upperBound.typeDepth())
}
internal fun SimpleType.typeDepth(): Int {
if (this is TypeUtils.SpecialType) return 0
val maxInArguments = arguments.asSequence().map {
if (it.isStarProjection) 1 else it.type.unwrap().typeDepth()
}.max() ?: 0
return maxInArguments + 1
} }
//
//internal fun KotlinTypeMarker.typeDepth() =
// when (this) {
// is SimpleTypeMarker -> typeDepth()
// is FlexibleType -> Math.max(lowerBound.typeDepth(), upperBound.typeDepth())
// }
//
//internal fun SimpleTypeMarker.typeDepth(): Int {
// if (this is TypeUtils.SpecialType) return 0
//
// val maxInArguments = arguments.asSequence().map {
// if (it.isStarProjection) 1 else it.type.unwrap().typeDepth()
// }.max() ?: 0
//
// return maxInArguments + 1
//}
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.types
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.model.StubTypeMarker
// This type is used as a stub for postponed type variables, which are important for coroutine inference // This type is used as a stub for postponed type variables, which are important for coroutine inference
class StubType( class StubType(
@@ -16,7 +17,7 @@ class StubType(
ErrorUtils.createErrorTypeConstructor("Constructor for non fixed type: $originalTypeVariable"), ErrorUtils.createErrorTypeConstructor("Constructor for non fixed type: $originalTypeVariable"),
override val memberScope: MemberScope = override val memberScope: MemberScope =
ErrorUtils.createErrorScope("Scope for non fixed type: $originalTypeVariable") ErrorUtils.createErrorScope("Scope for non fixed type: $originalTypeVariable")
) : SimpleType() { ) : SimpleType(), StubTypeMarker {
override val arguments: List<TypeProjection> override val arguments: List<TypeProjection>
get() = emptyList() get() = emptyList()
@@ -24,13 +24,9 @@ import org.jetbrains.kotlin.types.model.SimpleTypeMarker
import org.jetbrains.kotlin.types.model.TypeConstructorMarker import org.jetbrains.kotlin.types.model.TypeConstructorMarker
open class ClassicTypeCheckerContext(val errorTypeEqualsToAnything: Boolean, val allowedTypeVariable: Boolean = true) : ClassicTypeSystemContext, AbstractTypeCheckerContext() { open class ClassicTypeCheckerContext(val errorTypeEqualsToAnything: Boolean, val allowedTypeVariable: Boolean = true) : ClassicTypeSystemContext, AbstractTypeCheckerContext() {
override fun intersectTypes(types: List<KotlinTypeMarker>): KotlinTypeMarker {
@Suppress("UNCHECKED_CAST")
return org.jetbrains.kotlin.types.checker.intersectTypes(types as List<UnwrappedType>)
}
override fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker { override fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker {
return super.prepareType(transformToNewType((type as KotlinType).unwrap())) return transformToNewType((type as KotlinType).unwrap())
} }
override val isErrorTypeEqualsToAnything: Boolean override val isErrorTypeEqualsToAnything: Boolean
@@ -54,22 +50,26 @@ open class ClassicTypeCheckerContext(val errorTypeEqualsToAnything: Boolean, val
} }
override fun substitutionSupertypePolicy(type: SimpleTypeMarker): SupertypesPolicy.DoCustomTransform { override fun substitutionSupertypePolicy(type: SimpleTypeMarker): SupertypesPolicy.DoCustomTransform {
require(type is SimpleType, type::errorMessage) return classicSubstitutionSupertypePolicy(type)
}
val substitutor = TypeConstructorSubstitution.create(type).buildSubstitutor() override val KotlinTypeMarker.isAllowedTypeVariable: Boolean get() = this is UnwrappedType && allowedTypeVariable && constructor is NewTypeVariableConstructor
return object : SupertypesPolicy.DoCustomTransform() { companion object {
override fun transformType(context: AbstractTypeCheckerContext, type: KotlinTypeMarker): SimpleTypeMarker { fun ClassicTypeSystemContext.classicSubstitutionSupertypePolicy(type: SimpleTypeMarker): SupertypesPolicy.DoCustomTransform {
return substitutor.safeSubstitute( require(type is SimpleType, type::errorMessage)
type.lowerBoundIfFlexible() as KotlinType, val substitutor = TypeConstructorSubstitution.create(type).buildSubstitutor()
Variance.INVARIANT
).asSimpleType()!! return object : SupertypesPolicy.DoCustomTransform() {
override fun transformType(context: AbstractTypeCheckerContext, type: KotlinTypeMarker): SimpleTypeMarker {
return substitutor.safeSubstitute(
type.lowerBoundIfFlexible() as KotlinType,
Variance.INVARIANT
).asSimpleType()!!
}
} }
} }
} }
override val KotlinTypeMarker.isAllowedTypeVariable: Boolean get() = this is UnwrappedType && allowedTypeVariable && constructor is NewTypeVariableConstructor
} }
private fun Any.errorMessage(): String { private fun Any.errorMessage(): String {
@@ -8,14 +8,18 @@ package org.jetbrains.kotlin.types.checker
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES import org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.resolve.calls.inference.CapturedType import org.jetbrains.kotlin.resolve.calls.inference.CapturedType
import org.jetbrains.kotlin.resolve.descriptorUtil.hasExactAnnotation
import org.jetbrains.kotlin.resolve.descriptorUtil.hasNoInferAnnotation
import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.model.* import org.jetbrains.kotlin.types.model.*
import org.jetbrains.kotlin.types.model.CaptureStatus import org.jetbrains.kotlin.types.model.CaptureStatus
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
import org.jetbrains.kotlin.types.typeUtil.contains
interface ClassicTypeSystemContext : TypeSystemContext { interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext {
override fun TypeConstructorMarker.isDenotable(): Boolean { override fun TypeConstructorMarker.isDenotable(): Boolean {
require(this is TypeConstructor, this::errorMessage) require(this is TypeConstructor, this::errorMessage)
return this.isDenotable return this.isDenotable
@@ -134,6 +138,13 @@ interface ClassicTypeSystemContext : TypeSystemContext {
} }
private fun TypeVariance.convertVariance(): Variance {
return when (this) {
TypeVariance.INV -> Variance.INVARIANT
TypeVariance.IN -> Variance.IN_VARIANCE
TypeVariance.OUT -> Variance.OUT_VARIANCE
}
}
override fun TypeArgumentMarker.getType(): KotlinTypeMarker { override fun TypeArgumentMarker.getType(): KotlinTypeMarker {
require(this is TypeProjection, this::errorMessage) require(this is TypeProjection, this::errorMessage)
@@ -220,6 +231,11 @@ interface ClassicTypeSystemContext : TypeSystemContext {
return this.asTypeProjection() return this.asTypeProjection()
} }
override fun TypeConstructorMarker.isUnitTypeConstructor(): Boolean {
require(this is TypeConstructor, this::errorMessage)
return KotlinBuiltIns.isTypeConstructorForGivenClass(this, FQ_NAMES.unit)
}
/** /**
* *
* SingleClassifierType is one of the following types: * SingleClassifierType is one of the following types:
@@ -240,6 +256,231 @@ interface ClassicTypeSystemContext : TypeSystemContext {
require(this is KotlinType, this::errorMessage) require(this is KotlinType, this::errorMessage)
return typeConstructor().isNothingConstructor() && !TypeUtils.isNullableType(this) return typeConstructor().isNothingConstructor() && !TypeUtils.isNullableType(this)
} }
override fun KotlinTypeMarker.contains(predicate: (KotlinTypeMarker) -> Boolean): Boolean {
require(this is KotlinType, this::errorMessage)
return containsInternal(this, predicate)
}
override fun SimpleTypeMarker.typeDepth(): Int {
require(this is SimpleType, this::errorMessage)
return this.typeDepthInternal()
}
override fun KotlinTypeMarker.typeDepth(): Int {
require(this is UnwrappedType, this::errorMessage)
return this.typeDepthInternal()
}
override fun intersectTypes(types: List<KotlinTypeMarker>): KotlinTypeMarker {
@Suppress("UNCHECKED_CAST")
return org.jetbrains.kotlin.types.checker.intersectTypes(types as List<UnwrappedType>)
}
override fun intersectTypes(types: List<SimpleTypeMarker>): SimpleTypeMarker {
@Suppress("UNCHECKED_CAST")
return org.jetbrains.kotlin.types.checker.intersectTypes(types as List<SimpleType>)
}
override fun Collection<KotlinTypeMarker>.singleBestRepresentative(): KotlinTypeMarker? {
@Suppress("UNCHECKED_CAST")
return singleBestRepresentative(this as Collection<KotlinType>)
}
override fun KotlinTypeMarker.isUnit(): Boolean {
require(this is UnwrappedType, this::errorMessage)
return KotlinBuiltIns.isUnit(this)
}
override fun createFlexibleType(lowerBound: SimpleTypeMarker, upperBound: SimpleTypeMarker): KotlinTypeMarker {
require(lowerBound is SimpleType, this::errorMessage)
require(upperBound is SimpleType, this::errorMessage)
return KotlinTypeFactory.flexibleType(lowerBound, upperBound)
}
override fun KotlinTypeMarker.withNullability(nullable: Boolean): KotlinTypeMarker {
return when (this) {
is SimpleTypeMarker -> this.withNullability(nullable)
is FlexibleTypeMarker -> createFlexibleType(lowerBound().withNullability(nullable), upperBound().withNullability(nullable))
else -> error("sealed")
}
}
override fun newBaseTypeCheckerContext(errorTypesEqualToAnything: Boolean): AbstractTypeCheckerContext {
return ClassicTypeCheckerContext(errorTypesEqualToAnything)
}
override fun nullableNothingType(): SimpleTypeMarker {
return builtIns.nullableNothingType
}
override fun nullableAnyType(): SimpleTypeMarker {
return builtIns.nullableAnyType
}
override fun nothingType(): SimpleTypeMarker {
return builtIns.nothingType
}
val builtIns: KotlinBuiltIns get() = throw UnsupportedOperationException("Not supported")
override fun KotlinTypeMarker.makeDefinitelyNotNullOrNotNull(): KotlinTypeMarker {
require(this is UnwrappedType, this::errorMessage)
return makeDefinitelyNotNullOrNotNullInternal(this)
}
override fun SimpleTypeMarker.makeSimpleTypeDefinitelyNotNullOrNotNull(): SimpleTypeMarker {
require(this is SimpleType, this::errorMessage)
return makeSimpleTypeDefinitelyNotNullOrNotNullInternal(this)
}
override fun KotlinTypeMarker.removeAnnotations(): KotlinTypeMarker {
require(this is UnwrappedType, this::errorMessage)
return this.replaceAnnotations(Annotations.EMPTY)
}
override fun KotlinTypeMarker.hasExactAnnotation(): Boolean {
require(this is UnwrappedType, this::errorMessage)
return hasExactInternal(this)
}
override fun KotlinTypeMarker.hasNoInferAnnotation(): Boolean {
require(this is UnwrappedType, this::errorMessage)
return hasNoInferInternal(this)
}
override fun TypeVariableMarker.freshTypeConstructor(): TypeConstructorMarker {
errorSupportedOnlyInTypeInference()
}
override fun CapturedTypeMarker.typeConstructorProjection(): TypeArgumentMarker {
require(this is NewCapturedType, this::errorMessage)
return this.constructor.projection
}
override fun KotlinTypeMarker.isNullableType(): Boolean {
require(this is KotlinType, this::errorMessage)
return TypeUtils.isNullableType(this)
}
override fun createSimpleType(
constructor: TypeConstructorMarker,
arguments: List<TypeArgumentMarker>,
nullable: Boolean
): SimpleTypeMarker {
require(constructor is TypeConstructor, constructor::errorMessage)
@Suppress("UNCHECKED_CAST")
return KotlinTypeFactory.simpleType(Annotations.EMPTY, constructor, arguments as List<TypeProjection>, nullable)
}
override fun createTypeArgument(type: KotlinTypeMarker, variance: TypeVariance): TypeArgumentMarker {
require(type is KotlinType, type::errorMessage)
return TypeProjectionImpl(variance.convertVariance(), type)
}
override fun createStarProjection(typeParameter: TypeParameterMarker): TypeArgumentMarker {
require(typeParameter is TypeParameterDescriptor, typeParameter::errorMessage)
return StarProjectionImpl(typeParameter)
}
override fun KotlinTypeMarker.canHaveUndefinedNullability(): Boolean {
require(this is UnwrappedType, this::errorMessage)
return constructor is NewTypeVariableConstructor ||
constructor.declarationDescriptor is TypeParameterDescriptor ||
this is NewCapturedType
}
override fun SimpleTypeMarker.replaceArguments(newArguments: List<TypeArgumentMarker>): SimpleTypeMarker {
require(this is SimpleType, this::errorMessage)
return this.replace(newArguments as List<TypeProjection>)
}
override fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker {
require(type is UnwrappedType, type::errorMessage)
return NewKotlinTypeChecker.transformToNewType(type)
}
override fun DefinitelyNotNullTypeMarker.original(): SimpleTypeMarker {
require(this is DefinitelyNotNullType, this::errorMessage)
return this.original
}
override fun createCapturedType(
constructorProjection: TypeArgumentMarker,
constructorSupertypes: List<KotlinTypeMarker>,
lowerType: KotlinTypeMarker?,
captureStatus: CaptureStatus
): CapturedTypeMarker {
errorSupportedOnlyInTypeInference()
}
override fun typeSubstitutorByTypeConstructor(map: Map<TypeConstructorMarker, KotlinTypeMarker>): TypeSubstitutorMarker {
errorSupportedOnlyInTypeInference()
}
override fun TypeSubstitutorMarker.safeSubstitute(type: KotlinTypeMarker): KotlinTypeMarker {
errorSupportedOnlyInTypeInference()
}
override fun TypeVariableMarker.defaultType(): SimpleTypeMarker {
errorSupportedOnlyInTypeInference()
}
override fun createStubType(typeVariable: TypeVariableMarker): StubTypeMarker {
errorSupportedOnlyInTypeInference()
}
override fun findCommonIntegerLiteralTypesSuperType(explicitSupertypes: List<SimpleTypeMarker>): SimpleTypeMarker? {
@Suppress("UNCHECKED_CAST")
explicitSupertypes as List<SimpleType>
return IntegerLiteralTypeConstructor.findCommonSuperType(explicitSupertypes)
}
override fun TypeConstructorMarker.getApproximatedIntegerLiteralType(): KotlinTypeMarker {
require(this is IntegerLiteralTypeConstructor, this::errorMessage)
return this.getApproximatedType().unwrap()
}
}
private fun hasNoInferInternal(type: UnwrappedType): Boolean {
return type.hasNoInferAnnotation()
}
private fun hasExactInternal(type: UnwrappedType): Boolean {
return type.hasExactAnnotation()
}
private fun makeDefinitelyNotNullOrNotNullInternal(type: UnwrappedType): UnwrappedType {
return type.makeDefinitelyNotNullOrNotNull()
}
private fun makeSimpleTypeDefinitelyNotNullOrNotNullInternal(type: SimpleType): SimpleType {
return type.makeSimpleTypeDefinitelyNotNullOrNotNull()
}
private fun containsInternal(type: KotlinType, predicate: (KotlinTypeMarker) -> Boolean): Boolean = type.contains(predicate)
private fun singleBestRepresentative(collection: Collection<KotlinType>) = collection.singleBestRepresentative()
internal fun UnwrappedType.typeDepthInternal() =
when (this) {
is SimpleType -> typeDepthInternal()
is FlexibleType -> Math.max(lowerBound.typeDepthInternal(), upperBound.typeDepthInternal())
}
internal fun SimpleType.typeDepthInternal(): Int {
if (this is TypeUtils.SpecialType) return 0
val maxInArguments = arguments.asSequence().map {
if (it.isStarProjection) 1 else it.type.unwrap().typeDepthInternal()
}.max() ?: 0
return maxInArguments + 1
} }
@@ -248,6 +489,10 @@ private inline fun Any.errorMessage(): String {
return "ClassicTypeSystemContext couldn't handle: $this, ${this::class}" return "ClassicTypeSystemContext couldn't handle: $this, ${this::class}"
} }
private fun errorSupportedOnlyInTypeInference(): Nothing {
error("supported only in type inference context")
}
fun Variance.convertVariance(): TypeVariance { fun Variance.convertVariance(): TypeVariance {
return when (this) { return when (this) {
Variance.INVARIANT -> TypeVariance.INV Variance.INVARIANT -> TypeVariance.INV
@@ -30,20 +30,21 @@ import org.jetbrains.kotlin.types.model.CaptureStatus
import org.jetbrains.kotlin.types.typeUtil.* import org.jetbrains.kotlin.types.typeUtil.*
import org.jetbrains.kotlin.utils.addToStdlib.cast import org.jetbrains.kotlin.utils.addToStdlib.cast
object SimpleClassicTypeSystemContext : ClassicTypeSystemContext
object StrictEqualityTypeChecker { object StrictEqualityTypeChecker {
private val context = object : ClassicTypeSystemContext {}
/** /**
* String! != String & A<String!> != A<String>, also A<in Nothing> != A<out Any?> * String! != String & A<String!> != A<String>, also A<in Nothing> != A<out Any?>
* also A<*> != A<out Any?> * also A<*> != A<out Any?>
* different error types non-equals even errorTypeEqualToAnything * different error types non-equals even errorTypeEqualToAnything
*/ */
fun strictEqualTypes(a: UnwrappedType, b: UnwrappedType): Boolean { fun strictEqualTypes(a: UnwrappedType, b: UnwrappedType): Boolean {
return AbstractStrictEqualityTypeChecker.strictEqualTypes(context, a, b) return AbstractStrictEqualityTypeChecker.strictEqualTypes(SimpleClassicTypeSystemContext, a, b)
} }
fun strictEqualTypes(a: SimpleType, b: SimpleType): Boolean { fun strictEqualTypes(a: SimpleType, b: SimpleType): Boolean {
return AbstractStrictEqualityTypeChecker.strictEqualTypes(context, a, b) return AbstractStrictEqualityTypeChecker.strictEqualTypes(SimpleClassicTypeSystemContext, a, b)
} }
} }
@@ -64,11 +65,11 @@ object NewKotlinTypeChecker : KotlinTypeChecker {
ClassicTypeCheckerContext(false).equalTypes(a.unwrap(), b.unwrap()) ClassicTypeCheckerContext(false).equalTypes(a.unwrap(), b.unwrap())
fun ClassicTypeCheckerContext.equalTypes(a: UnwrappedType, b: UnwrappedType): Boolean { fun ClassicTypeCheckerContext.equalTypes(a: UnwrappedType, b: UnwrappedType): Boolean {
return AbstractTypeChecker.equalTypes(this, a, b) return AbstractTypeChecker.equalTypes(this as AbstractTypeCheckerContext, a, b)
} }
fun ClassicTypeCheckerContext.isSubtypeOf(subType: UnwrappedType, superType: UnwrappedType): Boolean { fun ClassicTypeCheckerContext.isSubtypeOf(subType: UnwrappedType, superType: UnwrappedType): Boolean {
return AbstractTypeChecker.isSubtypeOf(this, subType, superType) return AbstractTypeChecker.isSubtypeOf(this as AbstractTypeCheckerContext, subType, superType)
} }
fun transformToNewType(type: SimpleType): SimpleType { fun transformToNewType(type: SimpleType): SimpleType {
@@ -156,10 +157,9 @@ object NewKotlinTypeChecker : KotlinTypeChecker {
object NullabilityChecker { object NullabilityChecker {
fun isSubtypeOfAny(type: UnwrappedType): Boolean = fun isSubtypeOfAny(type: UnwrappedType): Boolean =
ClassicTypeCheckerContext(false).hasNotNullSupertype(type.lowerIfFlexible(), SupertypesPolicy.LowerIfFlexible) SimpleClassicTypeSystemContext
.newBaseTypeCheckerContext(false)
fun hasPathByNotMarkedNullableNodes(start: SimpleType, end: TypeConstructor) = .hasNotNullSupertype(type.lowerIfFlexible(), SupertypesPolicy.LowerIfFlexible)
ClassicTypeCheckerContext(false).hasPathByNotMarkedNullableNodes(start, end)
} }
fun UnwrappedType.hasSupertypeWithGivenTypeConstructor(typeConstructor: TypeConstructor) = fun UnwrappedType.hasSupertypeWithGivenTypeConstructor(typeConstructor: TypeConstructor) =
@@ -21,9 +21,7 @@ abstract class AbstractTypeCheckerContext : TypeSystemContext {
abstract fun areEqualTypeConstructors(a: TypeConstructorMarker, b: TypeConstructorMarker): Boolean abstract fun areEqualTypeConstructors(a: TypeConstructorMarker, b: TypeConstructorMarker): Boolean
abstract fun intersectTypes(types: List<KotlinTypeMarker>): KotlinTypeMarker override fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker {
open fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker {
return type return type
} }
@@ -146,6 +144,15 @@ abstract class AbstractTypeCheckerContext : TypeSystemContext {
} }
object AbstractTypeChecker { object AbstractTypeChecker {
fun isSubtypeOf(context: TypeCheckerProviderContext, subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean {
return AbstractTypeChecker.isSubtypeOf(context.newBaseTypeCheckerContext(true), subType, superType)
}
fun equalTypes(context: TypeCheckerProviderContext, a: KotlinTypeMarker, b: KotlinTypeMarker): Boolean {
return AbstractTypeChecker.equalTypes(context.newBaseTypeCheckerContext(false), a, b)
}
fun isSubtypeOf(context: AbstractTypeCheckerContext, subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean { fun isSubtypeOf(context: AbstractTypeCheckerContext, subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean {
if (subType === superType) return true if (subType === superType) return true
return context.completeIsSubTypeOf(context.prepareType(subType), context.prepareType(superType)) return context.completeIsSubTypeOf(context.prepareType(subType), context.prepareType(superType))
@@ -312,7 +319,7 @@ object AbstractTypeChecker {
!type.isDynamic() && !type.isDefinitelyNotNullType() && !type.isDynamic() && !type.isDefinitelyNotNullType() &&
type.lowerBoundIfFlexible().typeConstructor() == type.upperBoundIfFlexible().typeConstructor() type.lowerBoundIfFlexible().typeConstructor() == type.upperBoundIfFlexible().typeConstructor()
private fun effectiveVariance(declared: TypeVariance, useSite: TypeVariance): TypeVariance? { fun effectiveVariance(declared: TypeVariance, useSite: TypeVariance): TypeVariance? {
if (declared == TypeVariance.INV) return useSite if (declared == TypeVariance.INV) return useSite
if (useSite == TypeVariance.INV) return declared if (useSite == TypeVariance.INV) return declared
@@ -453,6 +460,14 @@ object AbstractNullabilityChecker {
fun isPossibleSubtype(context: AbstractTypeCheckerContext, subType: SimpleTypeMarker, superType: SimpleTypeMarker): Boolean = fun isPossibleSubtype(context: AbstractTypeCheckerContext, subType: SimpleTypeMarker, superType: SimpleTypeMarker): Boolean =
context.runIsPossibleSubtype(subType, superType) context.runIsPossibleSubtype(subType, superType)
fun isSubtypeOfAny(context: TypeCheckerProviderContext, type: KotlinTypeMarker): Boolean =
AbstractNullabilityChecker.isSubtypeOfAny(context.newBaseTypeCheckerContext(false), type)
fun isSubtypeOfAny(context: AbstractTypeCheckerContext, type: KotlinTypeMarker): Boolean =
with(context) {
hasNotNullSupertype(type.lowerBoundIfFlexible(), SupertypesPolicy.LowerIfFlexible)
}
private fun AbstractTypeCheckerContext.runIsPossibleSubtype(subType: SimpleTypeMarker, superType: SimpleTypeMarker): Boolean { private fun AbstractTypeCheckerContext.runIsPossibleSubtype(subType: SimpleTypeMarker, superType: SimpleTypeMarker): Boolean {
// it makes for case String? & Any <: String // it makes for case String? & Any <: String
assert(subType.isSingleClassifierType() || subType.typeConstructor().isIntersection() || subType.isAllowedTypeVariable) { assert(subType.isSingleClassifierType() || subType.typeConstructor().isIntersection() || subType.isAllowedTypeVariable) {
@@ -501,6 +516,9 @@ object AbstractNullabilityChecker {
if (it.isMarkedNullable()) SupertypesPolicy.None else supertypesPolicy if (it.isMarkedNullable()) SupertypesPolicy.None else supertypesPolicy
} }
fun TypeCheckerProviderContext.hasPathByNotMarkedNullableNodes(start: SimpleTypeMarker, end: TypeConstructorMarker) =
newBaseTypeCheckerContext(false).hasPathByNotMarkedNullableNodes(start, end)
fun AbstractTypeCheckerContext.hasPathByNotMarkedNullableNodes(start: SimpleTypeMarker, end: TypeConstructorMarker) = fun AbstractTypeCheckerContext.hasPathByNotMarkedNullableNodes(start: SimpleTypeMarker, end: TypeConstructorMarker) =
anySupertype(start, { anySupertype(start, {
it.isNotNullNothing() || (!it.isMarkedNullable() && isEqualTypeConstructors(it.typeConstructor(), end)) it.isNotNullNothing() || (!it.isMarkedNullable() && isEqualTypeConstructors(it.typeConstructor(), end))
@@ -0,0 +1,14 @@
/*
* 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
fun TypeVariableMarker.freshTypeConstructor(c: TypeSystemInferenceExtensionContext) = with(c) { freshTypeConstructor() }
fun TypeSubstitutorMarker.safeSubstitute(
c: TypeSystemInferenceExtensionContext,
type: KotlinTypeMarker
) = with(c) { safeSubstitute(type) }
fun TypeVariableMarker.defaultType(c: TypeSystemInferenceExtensionContext) = with(c) { defaultType() }
@@ -5,6 +5,8 @@
package org.jetbrains.kotlin.types.model package org.jetbrains.kotlin.types.model
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
interface KotlinTypeMarker interface KotlinTypeMarker
interface TypeArgumentMarker interface TypeArgumentMarker
interface TypeConstructorMarker interface TypeConstructorMarker
@@ -17,14 +19,21 @@ interface DefinitelyNotNullTypeMarker : SimpleTypeMarker
interface FlexibleTypeMarker : KotlinTypeMarker interface FlexibleTypeMarker : KotlinTypeMarker
interface DynamicTypeMarker : FlexibleTypeMarker interface DynamicTypeMarker : FlexibleTypeMarker
interface RawTypeMarker : FlexibleTypeMarker interface RawTypeMarker : FlexibleTypeMarker
interface StubTypeMarker : SimpleTypeMarker
interface TypeArgumentListMarker interface TypeArgumentListMarker
interface TypeVariableMarker
enum class TypeVariance { interface TypeSubstitutorMarker
IN,
OUT,
INV enum class TypeVariance(val presentation: String) {
IN("in"),
OUT("out"),
INV("");
override fun toString(): String = presentation
} }
@@ -35,6 +44,96 @@ interface TypeSystemOptimizationContext {
fun identicalArguments(a: SimpleTypeMarker, b: SimpleTypeMarker) = false fun identicalArguments(a: SimpleTypeMarker, b: SimpleTypeMarker) = false
} }
interface TypeSystemBuiltInsContext {
fun nullableNothingType(): SimpleTypeMarker
fun nullableAnyType(): SimpleTypeMarker
fun nothingType(): SimpleTypeMarker
}
interface TypeSystemTypeFactoryContext {
fun createFlexibleType(lowerBound: SimpleTypeMarker, upperBound: SimpleTypeMarker): KotlinTypeMarker
fun createSimpleType(constructor: TypeConstructorMarker, arguments: List<TypeArgumentMarker>, nullable: Boolean): SimpleTypeMarker
fun createTypeArgument(type: KotlinTypeMarker, variance: TypeVariance): TypeArgumentMarker
fun createStarProjection(typeParameter: TypeParameterMarker): TypeArgumentMarker
}
interface TypeCheckerProviderContext {
fun newBaseTypeCheckerContext(errorTypesEqualToAnything: Boolean): AbstractTypeCheckerContext
}
interface TypeSystemCommonSuperTypesContext : TypeSystemContext, TypeSystemTypeFactoryContext, TypeCheckerProviderContext {
fun KotlinTypeMarker.anySuperTypeConstructor(predicate: (TypeConstructorMarker) -> Boolean) =
newBaseTypeCheckerContext(false).anySupertype(lowerBoundIfFlexible(), {
predicate(it.typeConstructor())
}, { AbstractTypeCheckerContext.SupertypesPolicy.LowerIfFlexible })
fun KotlinTypeMarker.canHaveUndefinedNullability(): Boolean
fun SimpleTypeMarker.typeDepth(): Int
fun KotlinTypeMarker.typeDepth(): Int
fun findCommonIntegerLiteralTypesSuperType(explicitSupertypes: List<SimpleTypeMarker>): SimpleTypeMarker?
}
interface TypeSystemInferenceExtensionContextDelegate : TypeSystemInferenceExtensionContext
interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBuiltInsContext, TypeSystemCommonSuperTypesContext {
fun KotlinTypeMarker.contains(predicate: (KotlinTypeMarker) -> Boolean): Boolean
fun TypeConstructorMarker.isUnitTypeConstructor(): Boolean
fun TypeConstructorMarker.getApproximatedIntegerLiteralType(): KotlinTypeMarker
fun Collection<KotlinTypeMarker>.singleBestRepresentative(): KotlinTypeMarker?
fun KotlinTypeMarker.isUnit(): Boolean
fun KotlinTypeMarker.withNullability(nullable: Boolean): KotlinTypeMarker
fun KotlinTypeMarker.makeDefinitelyNotNullOrNotNull(): KotlinTypeMarker
fun SimpleTypeMarker.makeSimpleTypeDefinitelyNotNullOrNotNull(): SimpleTypeMarker
fun createCapturedType(
constructorProjection: TypeArgumentMarker,
constructorSupertypes: List<KotlinTypeMarker>,
lowerType: KotlinTypeMarker?,
captureStatus: CaptureStatus
): CapturedTypeMarker
fun createStubType(typeVariable: TypeVariableMarker): StubTypeMarker
fun KotlinTypeMarker.removeAnnotations(): KotlinTypeMarker
fun SimpleTypeMarker.replaceArguments(newArguments: List<TypeArgumentMarker>): SimpleTypeMarker
fun KotlinTypeMarker.hasExactAnnotation(): Boolean
fun KotlinTypeMarker.hasNoInferAnnotation(): Boolean
fun TypeVariableMarker.freshTypeConstructor(): TypeConstructorMarker
fun CapturedTypeMarker.typeConstructorProjection(): TypeArgumentMarker
fun KotlinTypeMarker.isNullableType(): Boolean
fun KotlinTypeMarker.isNullableAny() = this.typeConstructor().isAnyConstructor() && this.isNullableType()
fun KotlinTypeMarker.isNothing() = this.typeConstructor().isNothingConstructor() && !this.isNullableType()
fun KotlinTypeMarker.isNullableNothing() = this.typeConstructor().isNothingConstructor() && this.isNullableType()
fun DefinitelyNotNullTypeMarker.original(): SimpleTypeMarker
fun typeSubstitutorByTypeConstructor(map: Map<TypeConstructorMarker, KotlinTypeMarker>): TypeSubstitutorMarker
fun TypeSubstitutorMarker.safeSubstitute(type: KotlinTypeMarker): KotlinTypeMarker
fun TypeVariableMarker.defaultType(): SimpleTypeMarker
}
class ArgumentList(initialSize: Int) : ArrayList<TypeArgumentMarker>(initialSize), TypeArgumentListMarker class ArgumentList(initialSize: Int) : ArrayList<TypeArgumentMarker>(initialSize), TypeArgumentListMarker
@@ -53,6 +152,8 @@ interface TypeSystemContext : TypeSystemOptimizationContext {
fun FlexibleTypeMarker.lowerBound(): SimpleTypeMarker fun FlexibleTypeMarker.lowerBound(): SimpleTypeMarker
fun SimpleTypeMarker.asCapturedType(): CapturedTypeMarker? fun SimpleTypeMarker.asCapturedType(): CapturedTypeMarker?
fun KotlinTypeMarker.isCapturedType() = asSimpleType()?.asCapturedType() != null
fun SimpleTypeMarker.asDefinitelyNotNullType(): DefinitelyNotNullTypeMarker? fun SimpleTypeMarker.asDefinitelyNotNullType(): DefinitelyNotNullTypeMarker?
fun SimpleTypeMarker.isMarkedNullable(): Boolean fun SimpleTypeMarker.isMarkedNullable(): Boolean
fun SimpleTypeMarker.withNullability(nullable: Boolean): SimpleTypeMarker fun SimpleTypeMarker.withNullability(nullable: Boolean): SimpleTypeMarker
@@ -66,7 +167,7 @@ interface TypeSystemContext : TypeSystemOptimizationContext {
return null return null
} }
fun SimpleTypeMarker.isStubType(): Boolean = false fun SimpleTypeMarker.isStubType(): Boolean
fun KotlinTypeMarker.asTypeArgument(): TypeArgumentMarker fun KotlinTypeMarker.asTypeArgument(): TypeArgumentMarker
@@ -150,6 +251,13 @@ interface TypeSystemContext : TypeSystemOptimizationContext {
* Such types can contains error types in our arguments, but type constructor isn't errorTypeConstructor * Such types can contains error types in our arguments, but type constructor isn't errorTypeConstructor
*/ */
fun SimpleTypeMarker.isSingleClassifierType(): Boolean fun SimpleTypeMarker.isSingleClassifierType(): Boolean
fun intersectTypes(types: List<KotlinTypeMarker>): KotlinTypeMarker
fun intersectTypes(types: List<SimpleTypeMarker>): SimpleTypeMarker
fun KotlinTypeMarker.isSimpleType() = asSimpleType() != null
fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker
} }
enum class CaptureStatus { enum class CaptureStatus {
@@ -44,7 +44,7 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.*
val BackendContext.externalSymbols: ReferenceSymbolTable get() = ir.symbols.externalSymbolTable val BackendContext.externalSymbols: ReferenceSymbolTable get() = ir.symbols.externalSymbolTable
internal fun BackendContext.createTypeTranslator(moduleDescriptor: ModuleDescriptor): TypeTranslator = internal fun BackendContext.createTypeTranslator(moduleDescriptor: ModuleDescriptor): TypeTranslator =
TypeTranslator(externalSymbols, irBuiltIns.languageVersionSettings).apply { TypeTranslator(externalSymbols, irBuiltIns.languageVersionSettings, moduleDescriptor.builtIns).apply {
constantValueGenerator = ConstantValueGenerator(moduleDescriptor, symbolTable = externalSymbols) constantValueGenerator = ConstantValueGenerator(moduleDescriptor, symbolTable = externalSymbols)
constantValueGenerator.typeTranslator = this constantValueGenerator.typeTranslator = this
} }
@@ -57,6 +57,7 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ
import org.jetbrains.kotlin.synthetic.SamAdapterExtensionFunctionDescriptor import org.jetbrains.kotlin.synthetic.SamAdapterExtensionFunctionDescriptor
import org.jetbrains.kotlin.type.MapPsiToAsmDesc import org.jetbrains.kotlin.type.MapPsiToAsmDesc
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.types.typeUtil.isInterface import org.jetbrains.kotlin.types.typeUtil.isInterface
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.uast.* import org.jetbrains.uast.*
@@ -232,7 +233,7 @@ internal fun KotlinType.toPsiType(lightDeclaration: PsiModifierListOwner?, conte
val signatureWriter = BothSignatureWriter(BothSignatureWriter.Mode.TYPE) val signatureWriter = BothSignatureWriter(BothSignatureWriter.Mode.TYPE)
val typeMappingMode = if (boxed) TypeMappingMode.GENERIC_ARGUMENT else TypeMappingMode.DEFAULT val typeMappingMode = if (boxed) TypeMappingMode.GENERIC_ARGUMENT else TypeMappingMode.DEFAULT
val approximatedType = TypeApproximator().approximateDeclarationType(this, true, languageVersionSettings) val approximatedType = TypeApproximator(this.builtIns).approximateDeclarationType(this, true, languageVersionSettings)
typeMapper.mapType(approximatedType, signatureWriter, typeMappingMode) typeMapper.mapType(approximatedType, signatureWriter, typeMappingMode)
val signature = StringCharacterIterator(signatureWriter.toString()) val signature = StringCharacterIterator(signatureWriter.toString())