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:
@@ -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(
|
||||||
|
|||||||
+10
-5
@@ -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
|
||||||
+7
-5
@@ -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
|
||||||
|
|||||||
+3
-1
@@ -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)
|
||||||
|
|||||||
+1
-1
@@ -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
|
||||||
|
|||||||
+1
-1
@@ -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 {
|
||||||
|
|||||||
+1
-1
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
+90
-63
@@ -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
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+19
@@ -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
|
||||||
+87
@@ -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))
|
||||||
|
}
|
||||||
+5
-2
@@ -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(
|
||||||
|
|||||||
+17
-2
@@ -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
-10
@@ -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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-13
@@ -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 {
|
||||||
|
|||||||
+9
-5
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -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>
|
||||||
|
|
||||||
|
|||||||
+77
-73
@@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+81
-54
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
+54
-46
@@ -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()
|
||||||
|
|||||||
+10
-6
@@ -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>) {
|
||||||
|
|||||||
+2
-1
@@ -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
|
||||||
|
|||||||
+27
-29
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
-1
@@ -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 {
|
||||||
|
|||||||
+23
-17
@@ -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() }
|
|
||||||
|
|||||||
+28
-23
@@ -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)
|
||||||
|
|||||||
+35
-29
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+19
-18
@@ -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()) }
|
||||||
|
|
||||||
}
|
}
|
||||||
+10
-8
@@ -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)
|
||||||
+25
-21
@@ -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)
|
||||||
|
|||||||
+8
-5
@@ -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()
|
||||||
}
|
}
|
||||||
|
|||||||
+51
-46
@@ -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() }
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -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)
|
||||||
|
|||||||
+1
-1
@@ -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()
|
||||||
|
|||||||
+16
-16
@@ -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 {
|
||||||
|
|||||||
+246
-1
@@ -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 {
|
||||||
|
|||||||
+1
-1
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -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())
|
||||||
|
|||||||
Reference in New Issue
Block a user