diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt index 8d5846f060e..7d213952022 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt @@ -333,6 +333,23 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext { symbol is FirTypeParameterSymbol } + override fun intersectTypes(types: List): KotlinTypeMarker { + TODO("not implemented") + } + + override fun intersectTypes(types: List): 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 + override fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker { + return super.prepareType(type) + } + } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt b/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt index 7e72161793d..f47a8644e73 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.incremental.components.ExpectActualTracker import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.psi.KtFile 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.tower.KotlinResolutionStatelessCallbacksImpl import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker @@ -72,6 +73,7 @@ private fun StorageComponentContainer.configurePlatformIndependentComponents() { useImpl() useImpl() useImpl() + useImpl() } fun StorageComponentContainer.configureModule( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt index 50c91b3778e..b61c7cf9b07 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.resolve.constants.CompileTimeConstantChecker import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver +import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.utils.addToStdlib.safeAs class DiagnosticReporterByTrackingStrategy( @@ -212,19 +213,19 @@ class DiagnosticReporterByTrackingStrategy( val expression = it.psiExpression ?: return val deparenthesized = KtPsiUtil.safeDeparenthesize(expression) 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 { val call = it.topLevelCall.psiKotlinCall.psiCall.callElement.safeAs() 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 { 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 -> { @@ -247,10 +248,14 @@ class DiagnosticReporterByTrackingStrategy( val module = context.scope.ownerDescriptor.module val constantValue = constantExpressionEvaluator.evaluateToConstantValue(expression, trace, context.expectedType) val hasConstantTypeError = CompileTimeConstantChecker(context, module, true) - .checkConstantExpressionType(constantValue, expression, constraintError.upperType) + .checkConstantExpressionType(constantValue, expression, constraintError.upperKotlinType) if (hasConstantTypeError) return true } return false } -} \ No newline at end of file +} + + +val NewConstraintError.upperKotlinType get() = upperType as KotlinType +val NewConstraintError.lowerKotlinType get() = lowerType as KotlinType \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceSession.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceSession.kt index c910adf326c..63745c48ce9 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceSession.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceSession.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.TemporaryBindingTrace import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver 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.context.BasicCallResolutionContext 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.expressions.DoubleColonExpressionResolver import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices +import org.jetbrains.kotlin.utils.addToStdlib.cast class CoroutineInferenceSession( psiCallResolver: PSICallResolver, @@ -88,7 +90,7 @@ class CoroutineInferenceSession( updateCalls(lambda, commonSystem) - return commonSystem.fixedTypeVariables + return commonSystem.fixedTypeVariables.cast() // TODO: SUB } private fun createNonFixedTypeToVariableSubstitutor(): NewTypeSubstitutorByConstructorMap { @@ -117,8 +119,8 @@ class CoroutineInferenceSession( val callSubstitutor = storage.buildResultingSubstitutor() // substitutor only for fixed variables for (initialConstraint in storage.initialConstraints) { - val lower = nonFixedToVariablesSubstitutor.safeSubstitute(callSubstitutor.safeSubstitute(initialConstraint.a)) - val upper = nonFixedToVariablesSubstitutor.safeSubstitute(callSubstitutor.safeSubstitute(initialConstraint.b)) + val lower = nonFixedToVariablesSubstitutor.safeSubstitute(callSubstitutor.safeSubstitute(initialConstraint.a as UnwrappedType)) // TODO: SUB + val upper = nonFixedToVariablesSubstitutor.safeSubstitute(callSubstitutor.safeSubstitute(initialConstraint.b as UnwrappedType)) // TODO: SUB if (commonSystem.isProperType(lower) && commonSystem.isProperType(upper)) continue @@ -183,9 +185,9 @@ class CoroutineInferenceSession( nonFixedTypesToResult: Map ) { 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 resultCallAtom = completedCall.callResolutionResult.resultCallAtom diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt index 66f381623b8..e4ca5b9f3f1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt @@ -665,7 +665,9 @@ class NewResolvedCallImpl( typeArguments = resolvedCallAtom.substitutor.freshVariables.map { 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) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt index 6ba0cf30eac..03e01cd5277 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt @@ -134,7 +134,7 @@ class ResolvedAtomCompleter( } val approximatedReturnType = - TypeApproximator().approximateDeclarationType( + TypeApproximator(builtIns).approximateDeclarationType( returnType, local = true, languageVersionSettings = topLevelCallContext.languageVersionSettings diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmCoercionToUnitPatcher.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmCoercionToUnitPatcher.kt index dbfe007388b..cd53c7ff706 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmCoercionToUnitPatcher.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmCoercionToUnitPatcher.kt @@ -28,7 +28,7 @@ internal val jvmCoercionToUnitPhase = makeIrFilePhase( class JvmCoercionToUnitPatcher(val context: JvmBackendContext) : InsertImplicitCasts( context.builtIns, context.irBuiltIns, - TypeTranslator(context.ir.symbols.externalSymbolTable, context.state.languageVersionSettings), + TypeTranslator(context.ir.symbols.externalSymbolTable, context.state.languageVersionSettings, context.builtIns), JvmGeneratorExtensions.samConversion ), FileLoweringPass { diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/GeneratorContext.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/GeneratorContext.kt index b50d709b27a..e84110569a1 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/GeneratorContext.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/GeneratorContext.kt @@ -40,7 +40,7 @@ class GeneratorContext( ) : IrGeneratorContext() { val constantValueGenerator: ConstantValueGenerator = ConstantValueGenerator(moduleDescriptor, symbolTable) - val typeTranslator: TypeTranslator = TypeTranslator(symbolTable, languageVersionSettings) + val typeTranslator: TypeTranslator = TypeTranslator(symbolTable, languageVersionSettings, builtIns = moduleDescriptor.builtIns) init { typeTranslator.constantValueGenerator = constantValueGenerator diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt index edeb3461218..9e4415d7e85 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt @@ -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) init { diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/TypeTranslator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/TypeTranslator.kt index f4a9382fe7c..dae9111cd60 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/TypeTranslator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/TypeTranslator.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.ir.util +import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.ClassDescriptor @@ -25,11 +26,12 @@ import org.jetbrains.kotlin.types.typesApproximation.approximateCapturedTypes class TypeTranslator( private val symbolTable: ReferenceSymbolTable, val languageVersionSettings: LanguageVersionSettings, + builtIns: KotlinBuiltIns, private val typeParametersResolver: TypeParametersResolver = ScopedTypeParametersResolver(), private val enterTableScope: Boolean = false ) { - private val typeApproximatorForNI = TypeApproximator() + private val typeApproximatorForNI = TypeApproximator(builtIns) lateinit var constantValueGenerator: ConstantValueGenerator fun enterScope(irElement: IrTypeParametersContainer) { @@ -124,7 +126,11 @@ class TypeTranslator( if (ktType.constructor.isDenotable) return ktType return if (languageVersionSettings.supportsFeature(LanguageFeature.NewInference)) - typeApproximatorForNI.approximateDeclarationType(ktType, local = false, languageVersionSettings = languageVersionSettings) + typeApproximatorForNI.approximateDeclarationType( + ktType, + local = false, + languageVersionSettings = languageVersionSettings + ) else approximateCapturedTypes(ktType).upper } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/NewCommonSuperTypeCalculator.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/NewCommonSuperTypeCalculator.kt index aa682bbc0a8..d64df3bea50 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/NewCommonSuperTypeCalculator.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/NewCommonSuperTypeCalculator.kt @@ -21,17 +21,24 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.checker.* -import org.jetbrains.kotlin.types.typeUtil.asTypeProjection -import org.jetbrains.kotlin.types.typeUtil.canHaveUndefinedNullability +import org.jetbrains.kotlin.types.AbstractNullabilityChecker.hasPathByNotMarkedNullableNodes +import org.jetbrains.kotlin.types.model.* object NewCommonSuperTypeCalculator { + + // TODO: Bridge for old calls fun commonSuperType(types: List): UnwrappedType { + val ctx = object : ClassicTypeSystemContext {} + return ctx.commonSuperType(types) as UnwrappedType + } + + fun TypeSystemCommonSuperTypesContext.commonSuperType(types: List): KotlinTypeMarker { val maxDepth = types.maxBy { it.typeDepth() }?.typeDepth() ?: 0 return commonSuperType(types, -maxDepth) } - private fun commonSuperType(types: List, depth: Int): UnwrappedType { + private fun TypeSystemCommonSuperTypesContext.commonSuperType(types: List, depth: Int): KotlinTypeMarker { if (types.isEmpty()) throw IllegalStateException("Empty collection for input") types.singleOrNull()?.let { return it } @@ -40,49 +47,57 @@ object NewCommonSuperTypeCalculator { val lowers = types.map { when (it) { - is SimpleType -> it - is FlexibleType -> { - if (it is DynamicType) return it + is SimpleTypeMarker -> it + is FlexibleTypeMarker -> { + if (it.isDynamic()) return it // raw types are allowed here and will be transformed to FlexibleTypes thereIsFlexibleTypes = true - it.lowerBound + it.lowerBound() } + else -> error("sealed") } } val lowerSuperType = commonSuperTypeForSimpleTypes(lowers, depth) if (!thereIsFlexibleTypes) return lowerSuperType - val upperSuperType = commonSuperTypeForSimpleTypes(types.map { it.upperIfFlexible() }, depth) - return KotlinTypeFactory.flexibleType(lowerSuperType, upperSuperType) + val upperSuperType = commonSuperTypeForSimpleTypes(types.map { it.upperBoundIfFlexible() }, depth) + return createFlexibleType(lowerSuperType, upperSuperType) } - private fun commonSuperTypeForSimpleTypes(types: List, depth: Int): SimpleType { + private fun TypeSystemCommonSuperTypesContext.commonSuperTypeForSimpleTypes( + types: List, + depth: Int + ): SimpleTypeMarker { // i.e. result type also should be marked nullable - val notAllNotNull = types.any { !NullabilityChecker.isSubtypeOfAny(it) } - val notNullTypes = if (notAllNotNull) types.map { it.makeNullableAsSpecified(false) } else types + val notAllNotNull = types.any { !AbstractNullabilityChecker.isSubtypeOfAny(this, it) } + val notNullTypes = if (notAllNotNull) types.map { it.withNullability(false) } else types val commonSuperType = commonSuperTypeForNotNullTypes(notNullTypes, depth) return if (notAllNotNull) - refineNullabilityForUndefinedNullability(types, commonSuperType) ?: commonSuperType.makeNullableAsSpecified(true) + refineNullabilityForUndefinedNullability(types, commonSuperType) ?: commonSuperType.withNullability(true) else commonSuperType } - private fun refineNullabilityForUndefinedNullability(types: List, commonSuperType: SimpleType): SimpleType? { - if (!commonSuperType.unwrap().canHaveUndefinedNullability()) return null + private fun TypeSystemCommonSuperTypesContext.refineNullabilityForUndefinedNullability( + types: List, + 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 } // Makes representative sample, i.e. (A, B, A) -> (A, B) - private fun List.uniquify(): List { - val uniqueTypes = arrayListOf() - for (type in this) { + private fun TypeSystemCommonSuperTypesContext.uniquify(types: List): List { + val uniqueTypes = arrayListOf() + for (type in types) { val isNewUniqueType = uniqueTypes.all { - !NewKotlinTypeChecker.equalTypes(it, type) || it.constructor is IntegerLiteralTypeConstructor + !AbstractTypeChecker.equalTypes(this, it, type) || it.typeConstructor().isIntegerLiteralTypeConstructor() } if (isNewUniqueType) { 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 // 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.filterSupertypes(): List { - val supertypes = this.toMutableList() + private fun TypeSystemCommonSuperTypesContext.filterSupertypes(list: List): List { + val supertypes = list.toMutableList() val iterator = supertypes.iterator() while (iterator.hasNext()) { val potentialSubtype = iterator.next() val isSubtype = supertypes.any { supertype -> - supertype !== potentialSubtype && NewKotlinTypeChecker.isSubtypeOf(potentialSubtype, supertype) + supertype !== potentialSubtype && AbstractTypeChecker.isSubtypeOf(this, potentialSubtype, supertype) } if (isSubtype) iterator.remove() @@ -108,28 +123,35 @@ object NewCommonSuperTypeCalculator { return supertypes } - private fun commonSuperTypeForNotNullTypes(types: List, depth: Int): SimpleType { + private fun TypeSystemCommonSuperTypesContext.commonSuperTypeForNotNullTypes( + types: List, + depth: Int + ): SimpleTypeMarker { if (types.size == 1) return types.single() - val uniqueTypes = types.uniquify() + val uniqueTypes = uniquify(types) if (uniqueTypes.size == 1) return uniqueTypes.single() - val explicitSupertypes = uniqueTypes.filterSupertypes() + val explicitSupertypes = filterSupertypes(uniqueTypes) 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) } - private fun findSuperTypeConstructorsAndIntersectResult(types: List, depth: Int): SimpleType { + private fun TypeSystemCommonSuperTypesContext.findSuperTypeConstructorsAndIntersectResult( + types: List, + depth: Int + ): SimpleTypeMarker { 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 */ - private fun allCommonSuperTypeConstructors(types: List): List { + private fun TypeSystemCommonSuperTypesContext.allCommonSuperTypeConstructors(types: List): List { val result = collectAllSupertypes(types.first()) for (type in types) { if (type === types.first()) continue @@ -138,22 +160,22 @@ object NewCommonSuperTypeCalculator { } return result.filterNot { target -> 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().apply { - type.anySuperTypeConstructor { add(it); false } - } + private fun TypeSystemCommonSuperTypesContext.collectAllSupertypes(type: SimpleTypeMarker) = + LinkedHashSet().apply { + type.anySuperTypeConstructor { add(it); false } + } - private fun superTypeWithGivenConstructor( - types: List, - constructor: TypeConstructor, + private fun TypeSystemCommonSuperTypesContext.superTypeWithGivenConstructor( + types: List, + constructor: TypeConstructorMarker, depth: Int - ): SimpleType { - if (constructor.parameters.isEmpty()) return KotlinTypeFactory.simpleType( - Annotations.EMPTY, + ): SimpleTypeMarker { + if (constructor.parametersCount() == 0) return createSimpleType( constructor, emptyList(), nullable = false @@ -168,17 +190,18 @@ object NewCommonSuperTypeCalculator { * but it is too complicated and we will return not so accurate type: CS(List, List, List) */ val correspondingSuperTypes = types.flatMap { - with(NewKotlinTypeChecker) { + with(AbstractTypeChecker) { typeCheckerContext.findCorrespondingSupertypes(it, constructor) } } - val arguments = ArrayList(constructor.parameters.size) - for ((index, parameter) in constructor.parameters.withIndex()) { + val arguments = ArrayList(constructor.parametersCount()) + for (index in 0 until constructor.parametersCount()) { + val parameter = constructor.getParameter(index) var thereIsStar = false val typeProjections = correspondingSuperTypes.mapNotNull { - it.arguments.getOrNull(index)?.let { - if (it.isStarProjection) { + it.getArgumentOrNull(index)?.let { + if (it.isStarProjection()) { thereIsStar = true null } else it @@ -187,38 +210,42 @@ object NewCommonSuperTypeCalculator { val argument = if (thereIsStar || typeProjections.isEmpty()) { - StarProjectionImpl(parameter) + createStarProjection(parameter) } else { calculateArgument(parameter, typeProjections, depth) } arguments.add(argument) } - return KotlinTypeFactory.simpleType(Annotations.EMPTY, constructor, arguments, nullable = false) + return createSimpleType(constructor, arguments, nullable = false) } // no star projections in arguments - private fun calculateArgument(parameter: TypeParameterDescriptor, arguments: List, depth: Int): TypeProjection { + private fun TypeSystemCommonSuperTypesContext.calculateArgument( + parameter: TypeParameterMarker, + arguments: List, + depth: Int + ): TypeArgumentMarker { if (depth > 3) { - return StarProjectionImpl(parameter) + return createStarProjection(parameter) } // Inv, Inv = Inv - 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() - if (arguments.all { it.type == first.type }) return first + if (arguments.all { it.getType() == first.getType() }) return first } val asOut: Boolean - if (parameter.variance != Variance.INVARIANT) { - asOut = parameter.variance == Variance.OUT_VARIANCE + if (parameter.getVariance() != TypeVariance.INV) { + asOut = parameter.getVariance() == TypeVariance.OUT } else { - val thereIsOut = arguments.any { it.projectionKind == Variance.OUT_VARIANCE } - val thereIsIn = arguments.any { it.projectionKind == Variance.IN_VARIANCE } + val thereIsOut = arguments.any { it.getVariance() == TypeVariance.OUT } + val thereIsIn = arguments.any { it.getVariance() == TypeVariance.IN } if (thereIsOut) { if (thereIsIn) { // CS(Inv, Inv) = Inv<*> - return StarProjectionImpl(parameter) + return createStarProjection(parameter) } else { asOut = true } @@ -230,16 +257,16 @@ object NewCommonSuperTypeCalculator { // CS(Out, Out) = Out // CS(In, In) = In if (asOut) { - val type = commonSuperType(arguments.map { it.type.unwrap() }, depth + 1) - return if (parameter.variance != Variance.INVARIANT) return type.asTypeProjection() else TypeProjectionImpl( - Variance.OUT_VARIANCE, - type + val type = commonSuperType(arguments.map { it.getType() }, depth + 1) + return if (parameter.getVariance() != TypeVariance.INV) return type.asTypeArgument() else createTypeArgument( + type, + TypeVariance.OUT ) } else { - val type = intersectTypes(arguments.map { it.type.unwrap() }) - return if (parameter.variance != Variance.INVARIANT) return type.asTypeProjection() else TypeProjectionImpl( - Variance.IN_VARIANCE, - type + val type = intersectTypes(arguments.map { it.getType() }) + return if (parameter.getVariance() != TypeVariance.INV) return type.asTypeArgument() else createTypeArgument( + type, + TypeVariance.IN ) } } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/BuiltInsProvider.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/BuiltInsProvider.kt new file mode 100644 index 00000000000..b18bc3f91b8 --- /dev/null +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/BuiltInsProvider.kt @@ -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 \ No newline at end of file diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ClassicTypeSystemContextForCS.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ClassicTypeSystemContextForCS.kt new file mode 100644 index 00000000000..415f21fcbee --- /dev/null +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ClassicTypeSystemContextForCS.kt @@ -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, + 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 + ) + return NewCapturedType( + CaptureStatus.FOR_INCORPORATION, + newCapturedTypeConstructor, + lowerType = lowerType + ) + } + + override fun typeSubstitutorByTypeConstructor(map: Map): 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)) +} \ No newline at end of file diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt index 6548ddc9b2e..9c617f26115 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt @@ -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.model.* 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.TypeUtils import org.jetbrains.kotlin.types.UnwrappedType +import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext class KotlinCallCompleter( private val postponedArgumentsAnalyzer: PostponedArgumentsAnalyzer, @@ -196,13 +196,16 @@ class KotlinCallCompleter( private fun KotlinResolutionCandidate.hasProperNonTrivialLowerConstraints(typeVariable: UnwrappedType): Boolean { assert(csBuilder.isTypeVariable(typeVariable)) { "$typeVariable is not a type variable" } + val context = getSystem() as TypeSystemInferenceExtensionContext val constructor = typeVariable.constructor val variableWithConstraints = csBuilder.currentStorage().notFixedTypeVariables[constructor] ?: return false val constraints = variableWithConstraints.constraints 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) } + } private fun KotlinResolutionCandidate.computeReturnTypeWithSmartCastInfo( diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponeArgumentsChecks.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponeArgumentsChecks.kt index e5ba9375217..d703c38b7eb 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponeArgumentsChecks.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponeArgumentsChecks.kt @@ -19,10 +19,13 @@ package org.jetbrains.kotlin.resolve.calls.components import org.jetbrains.kotlin.builtins.* import org.jetbrains.kotlin.descriptors.annotations.Annotations 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.NewConstraintSystemImpl import org.jetbrains.kotlin.resolve.calls.inference.model.LHSArgumentConstraintPosition import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableForLambdaReturnType import org.jetbrains.kotlin.resolve.calls.model.* +import org.jetbrains.kotlin.types.TypeConstructor import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.typeUtil.builtIns import org.jetbrains.kotlin.utils.addToStdlib.safeAs @@ -141,7 +144,8 @@ private fun preprocessCallableReference( if (expectedType == null) return result val notCallableTypeConstructor = - csBuilder.getProperSuperTypeConstructors(expectedType).firstOrNull { !ReflectionTypes.isPossibleExpectedCallableType(it) } + csBuilder.getProperSuperTypeConstructors(expectedType) + .firstOrNull { !ReflectionTypes.isPossibleExpectedCallableType(it.requireIs()) } argument.lhsResult.safeAs()?.let { val lhsType = it.unboundDetailedReceiver.stableType @@ -151,7 +155,13 @@ private fun preprocessCallableReference( } } if (notCallableTypeConstructor != null) { - diagnosticsHolder.addDiagnostic(NotCallableExpectedType(argument, expectedType, notCallableTypeConstructor)) + diagnosticsHolder.addDiagnostic( + NotCallableExpectedType( + argument, + expectedType, + notCallableTypeConstructor.requireIs() + ) + ) } return result } @@ -163,3 +173,8 @@ private fun preprocessCollectionLiteralArgument( // todo add some checks about expected type return ResolvedCollectionLiteralAtom(collectionLiteralArgument, expectedType) } + +internal inline fun Any.requireIs(): T { + require(this is T) + return this +} \ No newline at end of file diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponedArgumentsAnalyzer.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponedArgumentsAnalyzer.kt index 9ee5b599b04..f8acd789502 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponedArgumentsAnalyzer.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponedArgumentsAnalyzer.kt @@ -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.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.model.* import org.jetbrains.kotlin.types.typeUtil.builtIns +import org.jetbrains.kotlin.utils.addToStdlib.cast class PostponedArgumentsAnalyzer( private val callableReferenceResolver: CallableReferenceResolver ) { - interface Context { - fun buildCurrentSubstitutor(additionalBindings: Map): NewTypeSubstitutor - fun bindingStubsForPostponedVariables(): Map + interface Context : TypeSystemInferenceExtensionContext { + fun buildCurrentSubstitutor(additionalBindings: Map): NewTypeSubstitutor + fun bindingStubsForPostponedVariables(): Map // 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 fun addOtherSystem(otherSystem: ConstraintStorage) @@ -64,7 +64,7 @@ class PostponedArgumentsAnalyzer( diagnosticHolder: KotlinDiagnosticsHolder ) { 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) @@ -87,7 +87,7 @@ class PostponedArgumentsAnalyzer( receiver, parameters, expectedTypeForReturnArguments, - stubsForPostponedVariables + stubsForPostponedVariables.cast() ) returnArguments.forEach { c.addSubsystemFromArgument(it) } @@ -115,7 +115,7 @@ class PostponedArgumentsAnalyzer( val variable = variableWithConstraints.typeVariable c.getBuilder().unmarkPostponedVariable(variable) - c.getBuilder().addEqualityConstraint(variable.defaultType, resultType, CoroutinePosition()) + c.getBuilder().addEqualityConstraint(variable.defaultType(c), resultType, CoroutinePosition()) } } } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilder.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilder.kt index 545a240ded8..b975d0c5767 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilder.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilder.kt @@ -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.model.* 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 interface ConstraintSystemOperation { val hasContradiction: Boolean - fun registerVariable(variable: NewTypeVariable) - fun markPostponedVariable(variable: NewTypeVariable) - fun unmarkPostponedVariable(variable: NewTypeVariable) + fun registerVariable(variable: TypeVariableMarker) + fun markPostponedVariable(variable: TypeVariableMarker) + fun unmarkPostponedVariable(variable: TypeVariableMarker) - fun addSubtypeConstraint(lowerType: UnwrappedType, upperType: UnwrappedType, position: ConstraintPosition) - fun addEqualityConstraint(a: UnwrappedType, b: UnwrappedType, position: ConstraintPosition) + fun addSubtypeConstraint(lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker, position: ConstraintPosition) + fun addEqualityConstraint(a: KotlinTypeMarker, b: KotlinTypeMarker, position: ConstraintPosition) - fun isProperType(type: UnwrappedType): Boolean - fun isTypeVariable(type: UnwrappedType): Boolean - fun isPostponedTypeVariable(typeVariable: NewTypeVariable): Boolean + fun isProperType(type: KotlinTypeMarker): Boolean + fun isTypeVariable(type: KotlinTypeMarker): Boolean + fun isPostponedTypeVariable(typeVariable: TypeVariableMarker): Boolean - fun getProperSuperTypeConstructors(type: UnwrappedType): List + fun getProperSuperTypeConstructors(type: KotlinTypeMarker): List } interface ConstraintSystemBuilder : ConstraintSystemOperation { - val builtIns: KotlinBuiltIns + //val builtIns: KotlinBuiltIns // if runOperations return true, then this operation will be applied, and function return true fun runTransaction(runOperations: ConstraintSystemOperation.() -> Boolean): Boolean @@ -54,8 +56,8 @@ interface ConstraintSystemBuilder : ConstraintSystemOperation { } fun ConstraintSystemBuilder.addSubtypeConstraintIfCompatible( - lowerType: UnwrappedType, - upperType: UnwrappedType, + lowerType: KotlinTypeMarker, + upperType: KotlinTypeMarker, position: ConstraintPosition ) = runTransaction { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/InferenceUtils.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/InferenceUtils.kt index e84bf68fc13..649e5431158 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/InferenceUtils.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/InferenceUtils.kt @@ -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.NewTypeSubstitutorByConstructorMap 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.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): NewTypeSubstitutorByConstructorMap = - NewTypeSubstitutorByConstructorMap(fixedTypeVariables.entries.associate { it.key to it.value } + additionalBindings) +fun ConstraintStorage.buildCurrentSubstitutor(additionalBindings: Map): NewTypeSubstitutorByConstructorMap = + NewTypeSubstitutorByConstructorMap( (fixedTypeVariables.entries.associate { it.key to it.value } + additionalBindings).cast() ) // TODO: SUB fun ConstraintStorage.buildResultingSubstitutor(): NewTypeSubstitutor { val currentSubstitutorMap = fixedTypeVariables.entries.associate { @@ -33,11 +37,11 @@ fun ConstraintStorage.buildResultingSubstitutor(): NewTypeSubstitutor { val uninferredSubstitutorMap = notFixedTypeVariables.entries.associate { (freshTypeConstructor, typeVariable) -> freshTypeConstructor to ErrorUtils.createErrorTypeWithCustomConstructor( "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 @@ -63,7 +67,7 @@ fun CallableDescriptor.substituteAndApproximateCapturedTypes(substitutor: NewTyp override fun prepareTopLevelType(topLevelType: KotlinType, position: Variance) = substitutor.safeSubstitute(topLevelType.unwrap()).let { substitutedType -> - TypeApproximator().approximateToSuperType(substitutedType, TypeApproximatorConfiguration.CapturedAndIntegerLiteralsTypesApproximation) + TypeApproximator(builtIns).approximateToSuperType(substitutedType, TypeApproximatorConfiguration.CapturedAndIntegerLiteralsTypesApproximation) ?: substitutedType } } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/NewConstraintSystem.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/NewConstraintSystem.kt index 20ca62c7066..4dae8193500 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/NewConstraintSystem.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/NewConstraintSystem.kt @@ -24,7 +24,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic interface NewConstraintSystem { - val builtIns: KotlinBuiltIns +// val builtIns: KotlinBuiltIns val hasContradiction: Boolean val diagnostics: List diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TypeCheckerContextForConstraintSystem.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/AbstractTypeCheckerContextForConstraintSystem.kt similarity index 53% rename from compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TypeCheckerContextForConstraintSystem.kt rename to compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/AbstractTypeCheckerContextForConstraintSystem.kt index 888dc27319e..653d0ae2714 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TypeCheckerContextForConstraintSystem.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/AbstractTypeCheckerContextForConstraintSystem.kt @@ -5,34 +5,28 @@ package org.jetbrains.kotlin.resolve.calls.inference.components -import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.resolve.descriptorUtil.hasExactAnnotation -import org.jetbrains.kotlin.resolve.descriptorUtil.hasNoInferAnnotation -import org.jetbrains.kotlin.types.* -import org.jetbrains.kotlin.types.KotlinTypeFactory.flexibleType +import org.jetbrains.kotlin.types.AbstractNullabilityChecker +import org.jetbrains.kotlin.types.AbstractTypeChecker +import org.jetbrains.kotlin.types.AbstractTypeCheckerContext import org.jetbrains.kotlin.types.checker.* -import org.jetbrains.kotlin.types.model.CapturedTypeMarker -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 +import org.jetbrains.kotlin.types.model.* -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 - 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 { - require(subType is SimpleType) - require(superType is NewCapturedType) - return getLowerCapturedTypePolicy(subType, superType) - } - - private fun getLowerCapturedTypePolicy(subType: SimpleType, superType: NewCapturedType) = when { + override fun getLowerCapturedTypePolicy(subType: SimpleTypeMarker, superType: CapturedTypeMarker): LowerCapturedTypePolicy = when { isMyTypeVariable(subType) -> LowerCapturedTypePolicy.SKIP_LOWER subType.contains { it.anyBound(this::isMyTypeVariable) } -> LowerCapturedTypePolicy.CHECK_ONLY_LOWER else -> LowerCapturedTypePolicy.CHECK_SUBTYPE_AND_LOWER @@ -45,16 +39,14 @@ abstract class TypeCheckerContextForConstraintSystem : ClassicTypeCheckerContext * override val sameConstructorPolicy get() = SeveralSupertypesWithSameConstructorPolicy.TAKE_FIRST_FOR_SUBTYPING */ final override fun addSubtypeConstraint(subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean? { - require(subType is UnwrappedType) - require(superType is UnwrappedType) val hasNoInfer = subType.isTypeVariableWithNoInfer() || superType.isTypeVariableWithNoInfer() if (hasNoInfer) return true val hasExact = subType.isTypeVariableWithExact() || superType.isTypeVariableWithExact() // 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 mySuperType = if (hasExact) superType.replaceAnnotations(Annotations.EMPTY) else superType + val mySubType = if (hasExact) subType.removeAnnotations() else subType + val mySuperType = if (hasExact) superType.removeAnnotations() else superType val result = internalAddSubtypeConstraint(mySubType, mySuperType) if (!hasExact) return result @@ -65,13 +57,13 @@ abstract class TypeCheckerContextForConstraintSystem : ClassicTypeCheckerContext return (result ?: true) && (result2 ?: true) } - private fun UnwrappedType.isTypeVariableWithExact() = - anyBound(this@TypeCheckerContextForConstraintSystem::isMyTypeVariable) && hasExactAnnotation() + private fun KotlinTypeMarker.isTypeVariableWithExact() = + anyBound(this@AbstractTypeCheckerContextForConstraintSystem::isMyTypeVariable) && hasExactAnnotation() - private fun UnwrappedType.isTypeVariableWithNoInfer() = - anyBound(this@TypeCheckerContextForConstraintSystem::isMyTypeVariable) && hasNoInferAnnotation() + private fun KotlinTypeMarker.isTypeVariableWithNoInfer() = + anyBound(this@AbstractTypeCheckerContextForConstraintSystem::isMyTypeVariable) && hasNoInferAnnotation() - private fun internalAddSubtypeConstraint(subType: UnwrappedType, superType: UnwrappedType): Boolean? { + private fun internalAddSubtypeConstraint(subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean? { assertInputTypes(subType, superType) var answer: Boolean? = null @@ -92,12 +84,13 @@ abstract class TypeCheckerContextForConstraintSystem : ClassicTypeCheckerContext } // extract type variable only from type like Captured(out T) - private fun extractTypeVariableForSubtype(type: UnwrappedType): UnwrappedType? { - if (type !is NewCapturedType) return null + private fun extractTypeVariableForSubtype(type: KotlinTypeMarker): KotlinTypeMarker? { - val projection = type.constructor.projection - return if (projection.projectionKind == Variance.OUT_VARIANCE) - projection.type.takeIf { it is SimpleType && isMyTypeVariable(it) }?.unwrap() + val type = type.asSimpleType()?.asCapturedType() ?: return null + + val projection = type.typeConstructorProjection() + return if (projection.getVariance() == TypeVariance.OUT) + projection.getType().takeIf { it is SimpleTypeMarker && isMyTypeVariable(it) }?.asSimpleType() else null } @@ -139,35 +132,38 @@ abstract class TypeCheckerContextForConstraintSystem : ClassicTypeCheckerContext * * => (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) { - is SimpleType -> + is SimpleTypeMarker -> // Foo <: T or // Foo <: T? -- Foo!! <: T - if (typeVariable.isMarkedNullable) subType.makeDefinitelyNotNullOrNotNull() else subType + if (typeVariable.isMarkedNullable()) subType.makeDefinitelyNotNullOrNotNull() else subType - is FlexibleType -> { + is FlexibleTypeMarker -> { assertFlexibleTypeVariable(typeVariable) when (subType) { - is SimpleType -> + is SimpleTypeMarker -> // Foo <: T! -- (Foo!! .. Foo) <: T - flexibleType(subType.makeSimpleTypeDefinitelyNotNullOrNotNull(), subType) + createFlexibleType(subType.makeSimpleTypeDefinitelyNotNullOrNotNull(), subType) - is FlexibleType -> + is FlexibleTypeMarker -> // (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 } - private fun assertFlexibleTypeVariable(typeVariable: FlexibleType) { - assert(typeVariable.lowerBound.constructor == typeVariable.upperBound.constructor) { + private fun assertFlexibleTypeVariable(typeVariable: FlexibleTypeMarker) { + assert(typeVariable.lowerBound().typeConstructor() == typeVariable.upperBound().typeConstructor()) { "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 -- leave as is */ - private fun simplifyUpperConstraint(typeVariable: UnwrappedType, superType: UnwrappedType): Boolean { + private fun simplifyUpperConstraint(typeVariable: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean { @Suppress("NAME_SHADOWING") - val typeVariable = typeVariable.lowerIfFlexible() + val typeVariable = typeVariable.lowerBoundIfFlexible() @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 return superType.anyBound(this::isMyTypeVariable) || - isSubtypeOfByTypeChecker(typeVariable.builtIns.nullableNothingType, superType) + isSubtypeOfByTypeChecker(nullableNothingType(), superType) } return true } - private fun simplifyConstraintForPossibleIntersectionSubType(subType: UnwrappedType, superType: UnwrappedType): Boolean? { + private fun simplifyConstraintForPossibleIntersectionSubType(subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean? { @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 - 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 notTypeVariables = subIntersectionTypes.filterNot(this::isMyTypeVariable) // 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 } @@ -229,22 +231,22 @@ abstract class TypeCheckerContextForConstraintSystem : ClassicTypeCheckerContext // 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 // TODO: rethink, maybe we should take nullability into account somewhere else - if (notTypeVariables.any { NullabilityChecker.isSubtypeOfAny(it) }) { - return typeVariables.all { simplifyUpperConstraint(it, superType.makeNullableAsSpecified(true)) } + if (notTypeVariables.any { AbstractNullabilityChecker.isSubtypeOfAny(this as TypeCheckerProviderContext, it) }) { + return typeVariables.all { simplifyUpperConstraint(it, superType.withNullability(true)) } } return typeVariables.all { simplifyUpperConstraint(it, superType) } } - private fun isSubtypeOfByTypeChecker(subType: UnwrappedType, superType: UnwrappedType) = - with(NewKotlinTypeChecker) { this@TypeCheckerContextForConstraintSystem.isSubtypeOf(subType, superType) } + private fun isSubtypeOfByTypeChecker(subType: KotlinTypeMarker, superType: KotlinTypeMarker) = + AbstractTypeChecker.isSubtypeOf(this as AbstractTypeCheckerContext, subType, superType) - private fun assertInputTypes(subType: UnwrappedType, superType: UnwrappedType) { - fun correctSubType(subType: SimpleType) = - subType.isSingleClassifierType || subType.isIntersectionType || isMyTypeVariable(subType) || subType.isError || subType.isIntegerLiteralType + private fun assertInputTypes(subType: KotlinTypeMarker, superType: KotlinTypeMarker) { + fun correctSubType(subType: SimpleTypeMarker) = + subType.isSingleClassifierType() || subType.typeConstructor().isIntersection() || isMyTypeVariable(subType) || subType.isError() || subType.isIntegerLiteralType() - fun correctSuperType(superType: SimpleType) = - superType.isSingleClassifierType || superType.isIntersectionType || isMyTypeVariable(superType) || superType.isError || superType.isIntegerLiteralType + fun correctSuperType(superType: SimpleTypeMarker) = + superType.isSingleClassifierType() || superType.typeConstructor().isIntersection() || isMyTypeVariable(superType) || superType.isError() || superType.isIntegerLiteralType() assert(subType.bothBounds(::correctSubType)) { "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) { - is SimpleType -> f(this) - is FlexibleType -> f(lowerBound) && f(upperBound) + private inline fun KotlinTypeMarker.bothBounds(f: (SimpleTypeMarker) -> Boolean) = when (this) { + is SimpleTypeMarker -> f(this) + is FlexibleTypeMarker -> f(lowerBound()) && f(upperBound()) + else -> error("sealed") } - private inline fun UnwrappedType.anyBound(f: (SimpleType) -> Boolean) = when (this) { - is SimpleType -> f(this) - is FlexibleType -> f(lowerBound) || f(upperBound) + private inline fun KotlinTypeMarker.anyBound(f: (SimpleTypeMarker) -> Boolean) = when (this) { + is SimpleTypeMarker -> f(this) + is FlexibleTypeMarker -> f(lowerBound()) || f(upperBound()) + else -> error("sealed") } } \ No newline at end of file diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintIncorporator.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintIncorporator.kt index 4148f3f228d..d0e786dd390 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintIncorporator.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintIncorporator.kt @@ -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.ConstraintKind -import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraints import org.jetbrains.kotlin.types.* -import org.jetbrains.kotlin.types.checker.NewCapturedType -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.types.model.* import org.jetbrains.kotlin.utils.SmartSet import org.jetbrains.kotlin.utils.addIfNotNull import java.util.* @@ -24,130 +20,161 @@ class ConstraintIncorporator( val trivialConstraintTypeInferenceOracle: TrivialConstraintTypeInferenceOracle ) { - interface Context { + interface Context : TypeSystemInferenceExtensionContext { val allTypeVariablesWithConstraints: Collection // 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 + fun getConstraintsForVariable(typeVariable: TypeVariableMarker): Collection - fun addNewIncorporatedConstraint(lowerType: UnwrappedType, upperType: UnwrappedType) + fun addNewIncorporatedConstraint(lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker) } // \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 - if (constraint.type.contains { it.constructor == typeVariable.freshTypeConstructor }) return + with(c) { + if (constraint.type.contains { it.typeConstructor() == typeVariable.freshTypeConstructor() }) return + } - directWithVariable(c, typeVariable, constraint) - otherInsideMyConstraint(c, typeVariable, constraint) - insideOtherConstraint(c, typeVariable, constraint) + c.directWithVariable(typeVariable, constraint) + c.otherInsideMyConstraint(typeVariable, constraint) + c.insideOtherConstraint(typeVariable, constraint) } // 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 if (constraint.kind != ConstraintKind.LOWER) { - c.getConstraintsForVariable(typeVariable).forEach { + getConstraintsForVariable(typeVariable).forEach { if (it.kind != ConstraintKind.UPPER) { - c.addNewIncorporatedConstraint(it.type, constraint.type) + addNewIncorporatedConstraint(it.type, constraint.type) } } } // constraint.type <: \alpha if (constraint.kind != ConstraintKind.UPPER) { - c.getConstraintsForVariable(typeVariable).forEach { + getConstraintsForVariable(typeVariable).forEach { if (it.kind != ConstraintKind.LOWER) { - c.addNewIncorporatedConstraint(constraint.type, it.type) + addNewIncorporatedConstraint(constraint.type, it.type) } } } } // \alpha <: Inv<\beta>, \beta <: Number => \alpha <: Inv - private fun otherInsideMyConstraint(c: Context, typeVariable: NewTypeVariable, constraint: Constraint) { - val otherInMyConstraint = SmartSet.create() + private fun Context.otherInsideMyConstraint( + typeVariable: TypeVariableMarker, + constraint: Constraint + ) { + val otherInMyConstraint = SmartSet.create() constraint.type.contains { - otherInMyConstraint.addIfNotNull(c.getTypeVariable(it.constructor)) + otherInMyConstraint.addIfNotNull(this.getTypeVariable(it.typeConstructor())) false } for (otherTypeVariable in otherInMyConstraint) { // to avoid ConcurrentModificationException - val otherConstraints = ArrayList(c.getConstraintsForVariable(otherTypeVariable)) + val otherConstraints = ArrayList(this.getConstraintsForVariable(otherTypeVariable)) for (otherConstraint in otherConstraints) { - generateNewConstraint(c, typeVariable, constraint, otherTypeVariable, otherConstraint) + generateNewConstraint(typeVariable, constraint, otherTypeVariable, otherConstraint) } } } // \alpha <: Number, \beta <: Inv<\alpha> => \beta <: Inv - private fun insideOtherConstraint(c: Context, typeVariable: NewTypeVariable, constraint: Constraint) { - for (typeVariableWithConstraint in c.allTypeVariablesWithConstraints) { + private fun Context.insideOtherConstraint( + typeVariable: TypeVariableMarker, + constraint: Constraint + ) { + for (typeVariableWithConstraint in this@insideOtherConstraint.allTypeVariablesWithConstraints) { val constraintsWhichConstraintMyVariable = typeVariableWithConstraint.constraints.filter { - it.type.contains { it.constructor == typeVariable.freshTypeConstructor } + it.type.contains { it.typeConstructor() == typeVariable.freshTypeConstructor() } } constraintsWhichConstraintMyVariable.forEach { - generateNewConstraint(c, typeVariableWithConstraint.typeVariable, it, typeVariable, constraint) + generateNewConstraint(typeVariableWithConstraint.typeVariable, it, typeVariable, constraint) } } } - private fun generateNewConstraint( - c: Context, - targetVariable: NewTypeVariable, + private fun Context.generateNewConstraint( + targetVariable: TypeVariableMarker, baseConstraint: Constraint, - otherVariable: NewTypeVariable, + otherVariable: TypeVariableMarker, otherConstraint: Constraint ) { + val baseConstraintType = baseConstraint.type + val typeForApproximation = when (otherConstraint.kind) { ConstraintKind.EQUALITY -> { - baseConstraintType.substituteTypeVariable(otherVariable, otherConstraint.type) + baseConstraintType.substitute(this, otherVariable, otherConstraint.type) } ConstraintKind.UPPER -> { - val newCapturedTypeConstructor = NewCapturedTypeConstructor( - TypeProjectionImpl(Variance.OUT_VARIANCE, otherConstraint.type), - listOf(otherConstraint.type) + val temporaryCapturedType = createCapturedType( + createTypeArgument(otherConstraint.type, TypeVariance.OUT), + listOf(otherConstraint.type), + null, + CaptureStatus.FOR_INCORPORATION ) - val temporaryCapturedType = NewCapturedType( - CaptureStatus.FOR_INCORPORATION, - newCapturedTypeConstructor, - lowerType = null - ) - baseConstraintType.substituteTypeVariable(otherVariable, temporaryCapturedType) +// val newCapturedTypeConstructor = NewCapturedTypeConstructor( +// TypeProjectionImpl(Variance.OUT_VARIANCE, otherConstraint.type), +// listOf(otherConstraint.type) +// ) +// val temporaryCapturedType = NewCapturedType( +// CaptureStatus.FOR_INCORPORATION, +// newCapturedTypeConstructor, +// lowerType = null +// ) + baseConstraintType.substitute(this, otherVariable, temporaryCapturedType) } ConstraintKind.LOWER -> { - val newCapturedTypeConstructor = NewCapturedTypeConstructor( - TypeProjectionImpl(Variance.IN_VARIANCE, otherConstraint.type), - emptyList() + val temporaryCapturedType = createCapturedType( + createTypeArgument(otherConstraint.type, TypeVariance.IN), + emptyList(), + otherConstraint.type, + CaptureStatus.FOR_INCORPORATION ) - val temporaryCapturedType = NewCapturedType( - CaptureStatus.FOR_INCORPORATION, - newCapturedTypeConstructor, - lowerType = otherConstraint.type - ) - baseConstraintType.substituteTypeVariable(otherVariable, temporaryCapturedType) + +// val newCapturedTypeConstructor = NewCapturedTypeConstructor( +// TypeProjectionImpl(Variance.IN_VARIANCE, otherConstraint.type), +// emptyList() +// ) +// val temporaryCapturedType = NewCapturedType( +// CaptureStatus.FOR_INCORPORATION, +// newCapturedTypeConstructor, +// lowerType = otherConstraint.type +// ) + baseConstraintType.substitute(this, otherVariable, temporaryCapturedType) } } if (baseConstraint.kind != ConstraintKind.UPPER) { val generatedConstraintType = approximateCapturedTypes(typeForApproximation, toSuper = false) if (!trivialConstraintTypeInferenceOracle.isGeneratedConstraintTrivial(otherConstraint, generatedConstraintType)) { - c.addNewIncorporatedConstraint(generatedConstraintType, targetVariable.defaultType) + addNewIncorporatedConstraint(generatedConstraintType, targetVariable.defaultType()) } } if (baseConstraint.kind != ConstraintKind.LOWER) { val generatedConstraintType = approximateCapturedTypes(typeForApproximation, toSuper = true) 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 else typeApproximator.approximateToSubType(type, TypeApproximatorConfiguration.IncorporationConfiguration) ?: type } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintInjector.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintInjector.kt index 950f4b059d9..aec7bbb85b9 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintInjector.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintInjector.kt @@ -16,35 +16,31 @@ 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.ConstraintKind.LOWER import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind.UPPER import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.checker.NewCapturedType -import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker -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 org.jetbrains.kotlin.types.model.* import java.util.* class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val typeApproximator: TypeApproximator) { private val ALLOWED_DEPTH_DELTA_FOR_INCORPORATION = 1 - interface Context { - val allTypeVariables: Map + interface Context : TypeSystemInferenceExtensionContext { + val allTypeVariables: Map var maxTypeDepthFromInitialConstraints: Int - val notFixedTypeVariables: MutableMap - val fixedTypeVariables: MutableMap + val notFixedTypeVariables: MutableMap + val fixedTypeVariables: MutableMap fun addInitialConstraint(initialConstraint: InitialConstraint) 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 incorporationPosition = IncorporationConstraintPosition(position, initialConstraint) c.addInitialConstraint(initialConstraint) @@ -53,7 +49,7 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val 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 incorporationPosition = IncorporationConstraintPosition(position, initialConstraint) c.addInitialConstraint(initialConstraint) @@ -66,11 +62,11 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val private fun addSubTypeConstraintAndIncorporateIt( c: Context, - lowerType: UnwrappedType, - upperType: UnwrappedType, + lowerType: KotlinTypeMarker, + upperType: KotlinTypeMarker, incorporatePosition: IncorporationConstraintPosition ) { - val possibleNewConstraints = Stack>() + val possibleNewConstraints = Stack>() val typeCheckerContext = TypeCheckerContext(c, incorporatePosition, lowerType, upperType, possibleNewConstraints) typeCheckerContext.runIsSubtypeOf(lowerType, upperType) @@ -79,7 +75,7 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val if (c.shouldWeSkipConstraint(typeVariable, constraint)) continue 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 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()) } - private fun Context.shouldWeSkipConstraint(typeVariable: NewTypeVariable, constraint: Constraint): Boolean { + private fun Context.shouldWeSkipConstraint(typeVariable: TypeVariableMarker, constraint: Constraint): Boolean { assert(constraint.kind != ConstraintKind.EQUALITY) val constraintType = constraint.type if (!isAllowedType(constraintType)) return true - if (constraintType.constructor == typeVariable.freshTypeConstructor) { - if (constraintType.lowerIfFlexible().isMarkedNullable && constraint.kind == LOWER) return false // T? <: T + if (constraintType.typeConstructor() == typeVariable.freshTypeConstructor()) { + if (constraintType.lowerBoundIfFlexible().isMarkedNullable() && constraint.kind == LOWER) return false // T? <: T return true // T <: T(?!) } - if (constraintType is SimpleType) { + if (constraintType.isSimpleType()) { if (constraint.kind == UPPER && constraintType.isNullableAny()) return true // T <: Any? } return false } - private fun Context.isAllowedType(type: UnwrappedType) = + private fun Context.isAllowedType(type: KotlinTypeMarker) = type.typeDepth() <= maxTypeDepthFromInitialConstraints + ALLOWED_DEPTH_DELTA_FOR_INCORPORATION private inner class TypeCheckerContext( val c: Context, val position: IncorporationConstraintPosition, - val baseLowerType: UnwrappedType, - val baseUpperType: UnwrappedType, - val possibleNewConstraints: MutableList> - ) : TypeCheckerContextForConstraintSystem(), ConstraintIncorporator.Context { + val baseLowerType: KotlinTypeMarker, + val baseUpperType: KotlinTypeMarker, + val possibleNewConstraints: MutableList> + ) : AbstractTypeCheckerContextForConstraintSystem(), ConstraintIncorporator.Context, TypeSystemInferenceExtensionContext by c { - fun runIsSubtypeOf(lowerType: UnwrappedType, upperType: UnwrappedType) { - with(NewKotlinTypeChecker) { - if (!this@TypeCheckerContext.isSubtypeOf(lowerType, upperType)) { - // todo improve error reporting -- add information about base types - c.addError(NewConstraintError(lowerType, upperType, position)) - } + val baseContext: AbstractTypeCheckerContext = newBaseTypeCheckerContext(isErrorTypeEqualsToAnything) + + override fun substitutionSupertypePolicy(type: SimpleTypeMarker): SupertypesPolicy.DoCustomTransform { + return baseContext.substitutionSupertypePolicy(type) + } + + 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 - override fun isMyTypeVariable(type: SimpleType): Boolean = c.allTypeVariables.containsKey(type.constructor) + // from AbstractTypeCheckerContextForConstraintSystem + 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) - override fun addLowerConstraint(typeVariable: TypeConstructor, subType: UnwrappedType) = + override fun addLowerConstraint(typeVariable: TypeConstructorMarker, subType: KotlinTypeMarker) = addConstraint(typeVariable, subType, LOWER) - private fun isCapturedTypeFromSubtyping(type: UnwrappedType) = + private fun isCapturedTypeFromSubtyping(type: KotlinTypeMarker) = when ((type as? NewCapturedType)?.captureStatus) { null, CaptureStatus.FROM_EXPRESSION -> false 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()) } - private fun addConstraint(typeVariableConstructor: TypeConstructor, type: UnwrappedType, kind: ConstraintKind) { + private fun addConstraint(typeVariableConstructor: TypeConstructorMarker, type: KotlinTypeMarker, kind: ConstraintKind) { val typeVariable = c.allTypeVariables[typeVariableConstructor] ?: error("Should by type variableConstructor: $typeVariableConstructor. ${c.allTypeVariables.values}") var targetType = type - if (targetType.isError) { + if (targetType.isError()) { c.addError(ConstrainingTypeIsError(typeVariable, targetType, position)) return } @@ -163,7 +171,7 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val if (kind == UPPER) { val subType = typeApproximator.approximateToSubType(type, TypeApproximatorConfiguration.SubtypeCapturedTypesApproximation) - if (subType != null && !KotlinBuiltIns.isNothingOrNullableNothing(subType)) { + if (subType != null && !subType.typeConstructor().isNothingConstructor()) { targetType = subType } } @@ -171,7 +179,7 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val if (kind == LOWER) { val superType = 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 } } @@ -186,7 +194,7 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val } // from ConstraintIncorporator.Context - override fun addNewIncorporatedConstraint(lowerType: UnwrappedType, upperType: UnwrappedType) { + override fun addNewIncorporatedConstraint(lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker) { if (c.isAllowedType(lowerType) && c.isAllowedType(upperType)) { runIsSubtypeOf(lowerType, upperType) } @@ -195,7 +203,7 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val override val allTypeVariablesWithConstraints: Collection get() = c.notFixedTypeVariables.values - override fun getTypeVariable(typeConstructor: TypeConstructor): NewTypeVariable? { + override fun getTypeVariable(typeConstructor: TypeConstructorMarker): TypeVariableMarker? { val typeVariable = c.allTypeVariables[typeConstructor] if (typeVariable != null && !c.notFixedTypeVariables.containsKey(typeConstructor)) { fixedTypeVariable(typeVariable) @@ -203,11 +211,11 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val return typeVariable } - override fun getConstraintsForVariable(typeVariable: NewTypeVariable) = - c.notFixedTypeVariables[typeVariable.freshTypeConstructor]?.constraints + override fun getConstraintsForVariable(typeVariable: TypeVariableMarker) = + c.notFixedTypeVariables[typeVariable.freshTypeConstructor()]?.constraints ?: fixedTypeVariable(typeVariable) - fun fixedTypeVariable(variable: NewTypeVariable): Nothing { + fun fixedTypeVariable(variable: TypeVariableMarker): Nothing { error( "Type variable $variable should not be fixed!\n" + renderBaseConstraint() diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/KotlinConstraintSystemCompleter.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/KotlinConstraintSystemCompleter.kt index 8671de4befd..af5300fb980 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/KotlinConstraintSystemCompleter.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/KotlinConstraintSystemCompleter.kt @@ -11,7 +11,11 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraint import org.jetbrains.kotlin.resolve.calls.model.* 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.addIfNotNull +import org.jetbrains.kotlin.utils.addToStdlib.cast import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.kotlin.utils.addToStdlib.safeAs @@ -25,19 +29,19 @@ class KotlinConstraintSystemCompleter( } interface Context : VariableFixationFinder.Context, ResultTypeResolver.Context { - override val notFixedTypeVariables: Map + override val notFixedTypeVariables: Map - override val postponedTypeVariables: List + override val postponedTypeVariables: List // 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 fun addError(error: KotlinCallDiagnostic) - fun fixVariable(variable: NewTypeVariable, resultType: UnwrappedType) + fun fixVariable(variable: TypeVariableMarker, resultType: KotlinTypeMarker) } fun runCompletion( @@ -157,7 +161,7 @@ class KotlinConstraintSystemCompleter( c: Context, collectVariablesFromContext: Boolean, topLevelAtoms: List - ): List { + ): List { if (collectVariablesFromContext) return c.notFixedTypeVariables.keys.toList() fun ResolvedAtom.process(to: LinkedHashSet) { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/NewTypeSubstitutor.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/NewTypeSubstitutor.kt index 64775f1aba3..d4114f42d4b 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/NewTypeSubstitutor.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/NewTypeSubstitutor.kt @@ -12,8 +12,9 @@ import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.checker.NewCapturedType import org.jetbrains.kotlin.types.checker.NewCapturedTypeConstructor 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 safeSubstitute(type: UnwrappedType): UnwrappedType = substitute(type, runCapturedChecks = true, keepAnnotation = false) ?: type diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt index 7e4dfce31b8..66ad5bdf2b0 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt @@ -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.constants.IntegerLiteralTypeConstructor import org.jetbrains.kotlin.types.* -import org.jetbrains.kotlin.types.checker.intersectTypes -import org.jetbrains.kotlin.types.checker.isIntegerLiteralType -import org.jetbrains.kotlin.types.typeUtil.contains -import org.jetbrains.kotlin.utils.addToStdlib.safeAs +import org.jetbrains.kotlin.types.model.KotlinTypeMarker +import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext class ResultTypeResolver( val typeApproximator: TypeApproximator, val trivialConstraintTypeInferenceOracle: TrivialConstraintTypeInferenceOracle ) { - interface Context { - fun isProperType(type: UnwrappedType): Boolean + interface Context : TypeSystemInferenceExtensionContext { + 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 } // no proper constraints - return variableWithConstraints.typeVariable.freshTypeConstructor.builtIns.run { - if (direction == ResolveDirection.TO_SUBTYPE) nothingType else nullableAnyType + return run { + 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 } - val subType = findSubType(c, variableWithConstraints) - val superType = findSuperType(c, variableWithConstraints) + val subType = c.findSubType(variableWithConstraints) + val superType = c.findSuperType(variableWithConstraints) val result = if (direction == ResolveDirection.TO_SUBTYPE || direction == ResolveDirection.UNKNOWN) { c.resultType(subType, superType, variableWithConstraints) } else { @@ -61,10 +59,10 @@ class ResultTypeResolver( } private fun Context.resultType( - firstCandidate: UnwrappedType?, - secondCandidate: UnwrappedType?, + firstCandidate: KotlinTypeMarker?, + secondCandidate: KotlinTypeMarker?, variableWithConstraints: VariableWithConstraints - ): UnwrappedType? { + ): KotlinTypeMarker? { if (firstCandidate == null || secondCandidate == null) return firstCandidate ?: secondCandidate 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) { if (!isProperType(constraint.type)) continue if (!checkConstraint(constraint.type, constraint.kind, resultType)) return false @@ -87,11 +85,11 @@ class ResultTypeResolver( return true } - private fun findSubType(c: Context, variableWithConstraints: VariableWithConstraints): UnwrappedType? { - val lowerConstraints = variableWithConstraints.constraints.filter { it.kind == ConstraintKind.LOWER && c.isProperType(it.type) } + private fun Context.findSubType(variableWithConstraints: VariableWithConstraints): KotlinTypeMarker? { + val lowerConstraints = variableWithConstraints.constraints.filter { it.kind == ConstraintKind.LOWER && isProperType(it.type) } if (lowerConstraints.isNotEmpty()) { val types = sinkIntegerLiteralTypes(lowerConstraints.map { it.type }) - val commonSuperType = NewCommonSuperTypeCalculator.commonSuperType(types) + val commonSuperType = with(NewCommonSuperTypeCalculator) { commonSuperType(types) } /** * * fun Array.intersect(other: Iterable) { @@ -119,16 +117,16 @@ class ResultTypeResolver( return null } - private fun sinkIntegerLiteralTypes(types: List): List { + private fun Context.sinkIntegerLiteralTypes(types: List): List { return types.sortedBy { type -> - val containsILT = type.contains { it.unwrap().safeAs()?.isIntegerLiteralType ?: false } + val containsILT = type.contains { it.asSimpleType()?.isIntegerLiteralType() ?: false } if (containsILT) 1 else 0 } } - private fun findSuperType(c: Context, variableWithConstraints: VariableWithConstraints): UnwrappedType? { - val upperConstraints = variableWithConstraints.constraints.filter { it.kind == ConstraintKind.UPPER && c.isProperType(it.type) } + private fun Context.findSuperType(variableWithConstraints: VariableWithConstraints): KotlinTypeMarker? { + val upperConstraints = variableWithConstraints.constraints.filter { it.kind == ConstraintKind.UPPER && this@findSuperType.isProperType(it.type) } if (upperConstraints.isNotEmpty()) { val upperType = intersectTypes(upperConstraints.map { it.type }) @@ -137,22 +135,22 @@ class ResultTypeResolver( return null } - fun findResultIfThereIsEqualsConstraint(c: Context, variableWithConstraints: VariableWithConstraints): UnwrappedType? { + fun findResultIfThereIsEqualsConstraint(c: Context, variableWithConstraints: VariableWithConstraints): KotlinTypeMarker? = with(c) { val properEqualityConstraints = variableWithConstraints.constraints.filter { 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...) - private fun representativeFromEqualityConstraints(constraints: List): UnwrappedType? { + private fun Context.representativeFromEqualityConstraints(constraints: List): KotlinTypeMarker? { if (constraints.isEmpty()) return null val constraintTypes = constraints.map { it.type } - val nonLiteralTypes = constraintTypes.filter { it.constructor !is IntegerLiteralTypeConstructor } - return nonLiteralTypes.singleBestRepresentative()?.unwrap() - ?: constraintTypes.singleBestRepresentative()?.unwrap() + val nonLiteralTypes = constraintTypes.filter { it.typeConstructor() !is IntegerLiteralTypeConstructor } + return nonLiteralTypes.singleBestRepresentative() + ?: constraintTypes.singleBestRepresentative() ?: constraintTypes.first() // seems like constraint system has contradiction } } \ No newline at end of file diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/SimpleConstraintSystemImpl.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/SimpleConstraintSystemImpl.kt index d4989e5b963..46ccc79d3ad 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/SimpleConstraintSystemImpl.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/SimpleConstraintSystemImpl.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.resolve.calls.inference.components import org.jetbrains.kotlin.builtins.KotlinBuiltIns 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.model.NewConstraintSystemImpl 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 { - val csBuilder: ConstraintSystemBuilder = NewConstraintSystemImpl(constraintInjector, builtIns).getBuilder() + val csBuilder: ConstraintSystemBuilder = + NewConstraintSystemImpl(constraintInjector, ClassicTypeSystemContextForCS(builtIns)).getBuilder() override fun registerTypeVariables(typeParameters: Collection): TypeSubstitutor { val substitutionMap = typeParameters.associate { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TrivialConstraintTypeInferenceOracle.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TrivialConstraintTypeInferenceOracle.kt index 4ffd404f6ca..853a8aaedd5 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TrivialConstraintTypeInferenceOracle.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TrivialConstraintTypeInferenceOracle.kt @@ -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.ConstraintKind -import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable -import org.jetbrains.kotlin.types.UnwrappedType -import org.jetbrains.kotlin.types.typeUtil.contains -import org.jetbrains.kotlin.types.typeUtil.isNothing -import org.jetbrains.kotlin.types.typeUtil.isNullableNothing +import org.jetbrains.kotlin.types.model.KotlinTypeMarker +import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext +import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContextDelegate -class TrivialConstraintTypeInferenceOracle { +class TrivialConstraintTypeInferenceOracle(context: TypeSystemInferenceExtensionContextDelegate) : + TypeSystemInferenceExtensionContext by context { // 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(?). // 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 - 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 // 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 - fun isSuitableResultedType(resultType: UnwrappedType): Boolean { - return !resultType.isNothingOrNullableNothing() + fun isSuitableResultedType( + resultType: KotlinTypeMarker + ): Boolean { + return !resultType.typeConstructor().isNothingConstructor() } // 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 fun isGeneratedConstraintTrivial( otherConstraint: Constraint, - generatedConstraintType: UnwrappedType + generatedConstraintType: KotlinTypeMarker ): Boolean { if (generatedConstraintType.isNothing()) return true @@ -49,10 +52,13 @@ class TrivialConstraintTypeInferenceOracle { 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() } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TypeVariableDependencyInformationProvider.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TypeVariableDependencyInformationProvider.kt index 394365476c9..ee15d217cd5 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TypeVariableDependencyInformationProvider.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TypeVariableDependencyInformationProvider.kt @@ -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.model.PostponedResolvedAtom -import org.jetbrains.kotlin.types.TypeConstructor -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.freshTypeConstructor import org.jetbrains.kotlin.utils.SmartSet class TypeVariableDependencyInformationProvider( - private val notFixedTypeVariables: Map, + private val notFixedTypeVariables: Map, private val postponedKtPrimitives: List, - private val topLevelType: UnwrappedType? + private val topLevelType: KotlinTypeMarker?, + private val typeSystemContext: TypeSystemInferenceExtensionContext ) { // not oriented edges - private val constrainEdges: MutableMap> = hashMapOf() + private val constrainEdges: MutableMap> = hashMapOf() // oriented edges - private val postponeArgumentsEdges: MutableMap> = hashMapOf() + private val postponeArgumentsEdges: MutableMap> = hashMapOf() - private val relatedToAllOutputTypes: MutableSet = hashSetOf() - private val relatedToTopLevelType: MutableSet = hashSetOf() + private val relatedToAllOutputTypes: MutableSet = hashSetOf() + private val relatedToTopLevelType: MutableSet = hashSetOf() init { computeConstraintEdges() @@ -44,17 +46,17 @@ class TypeVariableDependencyInformationProvider( computeRelatedToTopLevelType() } - fun isVariableRelatedToTopLevelType(variable: TypeConstructor) = relatedToTopLevelType.contains(variable) - fun isVariableRelatedToAnyOutputType(variable: TypeConstructor) = relatedToAllOutputTypes.contains(variable) + fun isVariableRelatedToTopLevelType(variable: TypeConstructorMarker) = relatedToTopLevelType.contains(variable) + fun isVariableRelatedToAnyOutputType(variable: TypeConstructorMarker) = relatedToAllOutputTypes.contains(variable) private fun computeConstraintEdges() { - fun addConstraintEdge(from: TypeConstructor, to: TypeConstructor) { + fun addConstraintEdge(from: TypeConstructorMarker, to: TypeConstructorMarker) { constrainEdges.getOrPut(from) { hashSetOf() }.add(to) constrainEdges.getOrPut(to) { hashSetOf() }.add(from) } for (variableWithConstraints in notFixedTypeVariables.values) { - val from = variableWithConstraints.typeVariable.freshTypeConstructor + val from = variableWithConstraints.typeVariable.freshTypeConstructor(typeSystemContext) for (constraint in variableWithConstraints.constraints) { constraint.type.forAllMyTypeVariables { @@ -67,14 +69,14 @@ class TypeVariableDependencyInformationProvider( } private fun computePostponeArgumentsEdges() { - fun addPostponeArgumentsEdges(from: TypeConstructor, to: TypeConstructor) { + fun addPostponeArgumentsEdges(from: TypeConstructorMarker, to: TypeConstructorMarker) { postponeArgumentsEdges.getOrPut(from) { hashSetOf() }.add(to) } for (argument in postponedKtPrimitives) { if (argument.analyzed) continue - val typeVariablesInOutputType = SmartSet.create() + val typeVariablesInOutputType = SmartSet.create() (argument.outputType ?: continue).forAllMyTypeVariables { typeVariablesInOutputType.add(it) } 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 { - if (isMyTypeVariable(it.constructor)) action(it.constructor) + private fun KotlinTypeMarker.forAllMyTypeVariables(action: (TypeConstructorMarker) -> Unit) = + with(typeSystemContext) { + contains { + if (isMyTypeVariable(it.typeConstructor())) action(it.typeConstructor()) + false + } + } - false - } - private fun getConstraintEdges(from: TypeConstructor): Set = constrainEdges[from] ?: emptySet() - private fun getPostponeEdges(from: TypeConstructor): Set = postponeArgumentsEdges[from] ?: emptySet() + private fun getConstraintEdges(from: TypeConstructorMarker): Set = constrainEdges[from] ?: emptySet() + private fun getPostponeEdges(from: TypeConstructorMarker): Set = postponeArgumentsEdges[from] ?: emptySet() - private fun addAllRelatedNodes(to: MutableSet, node: TypeConstructor, includePostponedEdges: Boolean) { + private fun addAllRelatedNodes(to: MutableSet, node: TypeConstructorMarker, includePostponedEdges: Boolean) { if (to.add(node)) { for (relatedNode in getConstraintEdges(node)) { addAllRelatedNodes(to, relatedNode, includePostponedEdges) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TypeVariableDirectionCalculator.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TypeVariableDirectionCalculator.kt index 71500f0e239..e8f0f42e494 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TypeVariableDirectionCalculator.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TypeVariableDirectionCalculator.kt @@ -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.VariableWithConstraints import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtom -import org.jetbrains.kotlin.types.FlexibleType -import org.jetbrains.kotlin.types.SimpleType -import org.jetbrains.kotlin.types.UnwrappedType -import org.jetbrains.kotlin.types.Variance -import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker -import org.jetbrains.kotlin.types.checker.isIntersectionType +import org.jetbrains.kotlin.types.AbstractTypeChecker +import org.jetbrains.kotlin.types.model.FlexibleTypeMarker +import org.jetbrains.kotlin.types.model.KotlinTypeMarker +import org.jetbrains.kotlin.types.model.SimpleTypeMarker +import org.jetbrains.kotlin.types.model.TypeVariance import org.jetbrains.kotlin.utils.SmartList @@ -34,7 +33,7 @@ private typealias Variable = VariableWithConstraints class TypeVariableDirectionCalculator( private val c: VariableFixationFinder.Context, private val postponedKtPrimitives: List, - topLevelType: UnwrappedType + topLevelType: KotlinTypeMarker ) { enum class ResolveDirection { TO_SUBTYPE, @@ -55,7 +54,7 @@ class TypeVariableDirectionCalculator( fun getDirection(typeVariable: Variable): ResolveDirection = directions.getOrDefault(typeVariable, ResolveDirection.UNKNOWN) - private fun setupDirections(topReturnType: UnwrappedType) { + private fun setupDirections(topReturnType: KotlinTypeMarker) { topReturnType.visitType(ResolveDirection.TO_SUBTYPE) { variableWithConstraints, direction -> enterToNode(variableWithConstraints, direction) } @@ -105,47 +104,54 @@ class TypeVariableDirectionCalculator( !(direction == ResolveDirection.TO_SUBTYPE && constraint.kind == ConstraintKind.UPPER) && !(direction == ResolveDirection.TO_SUPERTYPE && constraint.kind == ConstraintKind.LOWER) - private fun UnwrappedType.visitType( + private fun KotlinTypeMarker.visitType( startDirection: ResolveDirection, action: (variable: Variable, direction: ResolveDirection) -> Unit - ) = - when (this) { - is SimpleType -> visitType(startDirection, action) - is FlexibleType -> { - lowerBound.visitType(startDirection, action) - upperBound.visitType(startDirection, action) + ) = when (this) { + is SimpleTypeMarker -> visitType(startDirection, action) + is FlexibleTypeMarker -> { + with(c) { + lowerBound().visitType(startDirection, action) + upperBound().visitType(startDirection, action) } } + else -> error("?!") + } - private fun SimpleType.visitType(startDirection: ResolveDirection, action: (variable: Variable, direction: ResolveDirection) -> Unit) { - if (isIntersectionType) { - constructor.supertypes.forEach { - it.unwrap().visitType(startDirection, action) + private fun SimpleTypeMarker.visitType( + startDirection: ResolveDirection, + action: (variable: Variable, direction: ResolveDirection) -> Unit + ): Unit = with(c) { + val constructor = typeConstructor() + if (constructor.isIntersection()) { + constructor.supertypes().forEach { + it.visitType(startDirection, action) } return } - if (arguments.isEmpty()) { + if (argumentsCount() == 0) { c.notFixedTypeVariables[constructor]?.let { action(it, startDirection) } return } - val parameters = constructor.parameters - if (parameters.size != arguments.size) return // incorrect type + if (constructor.parametersCount() != argumentsCount()) return // incorrect type - for ((argument, parameter) in arguments.zip(parameters)) { - if (argument.isStarProjection) continue + for (index in 0 until constructor.parametersCount()) { + 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) { - Variance.INVARIANT -> ResolveDirection.UNKNOWN - Variance.OUT_VARIANCE -> startDirection - Variance.IN_VARIANCE -> startDirection.opposite() + TypeVariance.INV -> ResolveDirection.UNKNOWN + TypeVariance.OUT -> startDirection + TypeVariance.IN -> startDirection.opposite() } - argument.type.unwrap().visitType(innerDirection, action) + argument.getType().visitType(innerDirection, action) } } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/VariableFixationFinder.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/VariableFixationFinder.kt index 5a04e974d0f..f37cdfa03b3 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/VariableFixationFinder.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/VariableFixationFinder.kt @@ -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.model.Constraint 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.model.PostponedResolvedAtom -import org.jetbrains.kotlin.types.TypeConstructor 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( private val trivialConstraintTypeInferenceOracle: TrivialConstraintTypeInferenceOracle ) { - interface Context { - val notFixedTypeVariables: Map - val postponedTypeVariables: List + interface Context : TypeSystemInferenceExtensionContext { + val notFixedTypeVariables: Map + val postponedTypeVariables: List } data class VariableForFixation( - val variable: TypeConstructor, + val variable: TypeConstructorMarker, val hasProperConstraint: Boolean, val hasOnlyTrivialProperConstraint: Boolean = false ) fun findFirstVariableForFixation( c: Context, - allTypeVariables: List, + allTypeVariables: List, postponedKtPrimitives: List, completionMode: ConstraintSystemCompletionMode, topLevelType: UnwrappedType @@ -59,7 +60,7 @@ class VariableFixationFinder( } private fun Context.getTypeVariableReadiness( - variable: TypeConstructor, + variable: TypeConstructorMarker, dependencyProvider: TypeVariableDependencyInformationProvider ): TypeVariableFixationReadiness = when { !notFixedTypeVariables.contains(variable) || @@ -72,13 +73,13 @@ class VariableFixationFinder( } private fun Context.findTypeVariableForFixation( - allTypeVariables: List, + allTypeVariables: List, postponedArguments: List, completionMode: ConstraintSystemCompletionMode, - topLevelType: UnwrappedType + topLevelType: KotlinTypeMarker ): VariableForFixation? { 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 @@ -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) { - 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 false } - private fun Context.variableHasTrivialOrNonProperConstraints(variable: TypeConstructor): Boolean { + private fun Context.variableHasTrivialOrNonProperConstraints(variable: TypeConstructorMarker): Boolean { return notFixedTypeVariables[variable]?.constraints?.all { constraint -> val isProperConstraint = isProperArgumentConstraint(constraint) isProperConstraint && trivialConstraintTypeInferenceOracle.isTrivialConstraint(constraint) || !isProperConstraint } ?: false } - private fun Context.variableHasProperArgumentConstraints(variable: TypeConstructor): Boolean = + private fun Context.variableHasProperArgumentConstraints(variable: TypeConstructorMarker): Boolean = notFixedTypeVariables[variable]?.constraints?.any { isProperArgumentConstraint(it) } ?: false private fun Context.isProperArgumentConstraint(c: Constraint) = isProperType(c.type) && c.position.initialConstraint.position !is DeclaredUpperBoundConstraintPosition - private fun Context.isProperType(type: UnwrappedType): Boolean = - !type.contains { notFixedTypeVariables.containsKey(it.constructor) } + private fun Context.isProperType(type: KotlinTypeMarker): Boolean = + !type.contains { notFixedTypeVariables.containsKey(it.typeConstructor()) } } \ No newline at end of file diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt index f8b67d04582..76007e657dc 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt @@ -24,6 +24,8 @@ import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.UnwrappedType +import org.jetbrains.kotlin.types.model.KotlinTypeMarker +import org.jetbrains.kotlin.types.model.TypeVariableMarker sealed class ConstraintPosition @@ -48,7 +50,7 @@ class ReceiverConstraintPosition(val argument: KotlinCallArgument) : ConstraintP override fun toString() = "Receiver $argument" } -class FixVariableConstraintPosition(val variable: NewTypeVariable) : ConstraintPosition() { +class FixVariableConstraintPosition(val variable: TypeVariableMarker) : ConstraintPosition() { override fun toString() = "Fix variable $variable" } @@ -88,21 +90,21 @@ abstract class ConstraintSystemCallDiagnostic(applicability: ResolutionCandidate } class NewConstraintError( - val lowerType: UnwrappedType, - val upperType: UnwrappedType, + val lowerType: KotlinTypeMarker, + val upperType: KotlinTypeMarker, val position: IncorporationConstraintPosition ) : ConstraintSystemCallDiagnostic(if (position.from is ReceiverConstraintPosition) INAPPLICABLE_WRONG_RECEIVER else INAPPLICABLE) class CapturedTypeFromSubtyping( - val typeVariable: NewTypeVariable, - val constraintType: UnwrappedType, + val typeVariable: TypeVariableMarker, + val constraintType: KotlinTypeMarker, val position: ConstraintPosition ) : ConstraintSystemCallDiagnostic(INAPPLICABLE) -class NotEnoughInformationForTypeParameter(val typeVariable: NewTypeVariable) : ConstraintSystemCallDiagnostic(INAPPLICABLE) +class NotEnoughInformationForTypeParameter(val typeVariable: TypeVariableMarker) : ConstraintSystemCallDiagnostic(INAPPLICABLE) class ConstrainingTypeIsError( - val typeVariable: NewTypeVariable, - val constraintType: UnwrappedType, + val typeVariable: TypeVariableMarker, + val constraintType: KotlinTypeMarker, val position: IncorporationConstraintPosition ) : ConstraintSystemCallDiagnostic(INAPPLICABLE) \ No newline at end of file diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintStorage.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintStorage.kt index f2d8c9f283e..9b950c30889 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintStorage.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintStorage.kt @@ -5,13 +5,13 @@ 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.types.TypeConstructor import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.types.UnwrappedType 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: @@ -36,24 +36,24 @@ import org.jetbrains.kotlin.types.checker.KotlinTypeChecker */ interface ConstraintStorage { - val allTypeVariables: Map - val notFixedTypeVariables: Map + val allTypeVariables: Map + val notFixedTypeVariables: Map val initialConstraints: List val maxTypeDepthFromInitialConstraints: Int val errors: List val hasContradiction: Boolean - val fixedTypeVariables: Map - val postponedTypeVariables: List + val fixedTypeVariables: Map + val postponedTypeVariables: List object Empty : ConstraintStorage { - override val allTypeVariables: Map get() = emptyMap() - override val notFixedTypeVariables: Map get() = emptyMap() + override val allTypeVariables: Map get() = emptyMap() + override val notFixedTypeVariables: Map get() = emptyMap() override val initialConstraints: List get() = emptyList() override val maxTypeDepthFromInitialConstraints: Int get() = 1 override val errors: List get() = emptyList() override val hasContradiction: Boolean get() = false - override val fixedTypeVariables: Map get() = emptyMap() - override val postponedTypeVariables: List get() = emptyList() + override val fixedTypeVariables: Map get() = emptyMap() + override val postponedTypeVariables: List get() = emptyList() } } @@ -69,7 +69,7 @@ enum class ConstraintKind { class Constraint( val kind: ConstraintKind, - val type: UnwrappedType, // flexible types here is allowed + val type: KotlinTypeMarker, // flexible types here is allowed val position: IncorporationConstraintPosition, val typeHashCode: Int = type.hashCode() ) { @@ -93,13 +93,13 @@ class Constraint( } interface VariableWithConstraints { - val typeVariable: NewTypeVariable + val typeVariable: TypeVariableMarker val constraints: List } class InitialConstraint( - val a: UnwrappedType, - val b: UnwrappedType, + val a: KotlinTypeMarker, + val b: KotlinTypeMarker, val constraintKind: ConstraintKind, // see [checkConstraint] val position: ConstraintPosition ) { @@ -114,13 +114,17 @@ class InitialConstraint( } } -fun InitialConstraint.checkConstraint(substitutor: TypeSubstitutor): Boolean { - val newA = substitutor.substitute(a) - val newB = substitutor.substitute(a) - return checkConstraint(newB, constraintKind, newA) -} +//fun InitialConstraint.checkConstraint(substitutor: TypeSubstitutor): Boolean { +// val newA = substitutor.substitute(a) +// val newB = substitutor.substitute(b) +// 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 return when (constraintKind) { ConstraintKind.EQUALITY -> typeChecker.equalTypes(constraintType, resultType) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/MutableConstraintStorage.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/MutableConstraintStorage.kt index 5cd03be9182..a9ffb742c44 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/MutableConstraintStorage.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/MutableConstraintStorage.kt @@ -11,12 +11,15 @@ import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic import org.jetbrains.kotlin.resolve.calls.tower.isSuccess 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 kotlin.collections.ArrayList import kotlin.collections.LinkedHashMap class MutableVariableWithConstraints( - override val typeVariable: NewTypeVariable, + override val typeVariable: TypeVariableMarker, constraints: Collection = emptyList() ) : VariableWithConstraints { override val constraints: List @@ -89,12 +92,12 @@ class MutableVariableWithConstraints( internal class MutableConstraintStorage : ConstraintStorage { - override val allTypeVariables: MutableMap = LinkedHashMap() - override val notFixedTypeVariables: MutableMap = LinkedHashMap() + override val allTypeVariables: MutableMap = LinkedHashMap() + override val notFixedTypeVariables: MutableMap = LinkedHashMap() override val initialConstraints: MutableList = ArrayList() override var maxTypeDepthFromInitialConstraints: Int = 1 override val errors: MutableList = ArrayList() override val hasContradiction: Boolean get() = errors.any { !it.candidateApplicability.isSuccess } - override val fixedTypeVariables: MutableMap = LinkedHashMap() - override val postponedTypeVariables: ArrayList = ArrayList() + override val fixedTypeVariables: MutableMap = LinkedHashMap() + override val postponedTypeVariables: ArrayList = ArrayList() } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt index e15748af0be..f9dc9e76415 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt @@ -6,24 +6,28 @@ package org.jetbrains.kotlin.resolve.calls.inference.model 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.inference.* -import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjector -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.inference.components.* import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic 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.typeUtil.contains -import org.jetbrains.kotlin.types.typeUtil.isUnit +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.SmartList +import org.jetbrains.kotlin.utils.addToStdlib.cast class NewConstraintSystemImpl( private val constraintInjector: ConstraintInjector, - override val builtIns: KotlinBuiltIns + val typeSystemContext: TypeSystemInferenceExtensionContext//, + //override val builtIns: KotlinBuiltIns ) : + TypeSystemInferenceExtensionContext by typeSystemContext, NewConstraintSystem, ConstraintSystemBuilder, ConstraintInjector.Context, @@ -32,7 +36,7 @@ class NewConstraintSystemImpl( PostponedArgumentsAnalyzer.Context { private val storage = MutableConstraintStorage() private var state = State.BUILDING - private val typeVariablesTransaction: MutableList = SmartList() + private val typeVariablesTransaction: MutableList = SmartList() private enum class State { BUILDING, @@ -63,23 +67,23 @@ class NewConstraintSystemImpl( override fun asPostponedArgumentsAnalyzerContext() = apply { checkState(State.BUILDING) } // ConstraintSystemOperation - override fun registerVariable(variable: NewTypeVariable) { + override fun registerVariable(variable: TypeVariableMarker) { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) transactionRegisterVariable(variable) - storage.allTypeVariables[variable.freshTypeConstructor] = variable - storage.notFixedTypeVariables[variable.freshTypeConstructor] = MutableVariableWithConstraints(variable) + storage.allTypeVariables[variable.freshTypeConstructor()] = variable + storage.notFixedTypeVariables[variable.freshTypeConstructor()] = MutableVariableWithConstraints(variable) } - override fun markPostponedVariable(variable: NewTypeVariable) { + override fun markPostponedVariable(variable: TypeVariableMarker) { storage.postponedTypeVariables += variable } - override fun unmarkPostponedVariable(variable: NewTypeVariable) { + override fun unmarkPostponedVariable(variable: TypeVariableMarker) { storage.postponedTypeVariables -= variable } - override fun addSubtypeConstraint(lowerType: UnwrappedType, upperType: UnwrappedType, position: ConstraintPosition) = + override fun addSubtypeConstraint(lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker, position: ConstraintPosition) = constraintInjector.addInitialSubtypeConstraint( apply { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) }, lowerType, @@ -87,7 +91,7 @@ class NewConstraintSystemImpl( position ) - override fun addEqualityConstraint(a: UnwrappedType, b: UnwrappedType, position: ConstraintPosition) = + override fun addEqualityConstraint(a: KotlinTypeMarker, b: KotlinTypeMarker, position: ConstraintPosition) = constraintInjector.addInitialEqualityConstraint( apply { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) }, a, @@ -95,18 +99,18 @@ class NewConstraintSystemImpl( position ) - override fun getProperSuperTypeConstructors(type: UnwrappedType): List { + override fun getProperSuperTypeConstructors(type: KotlinTypeMarker): List { 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 { if (it.kind == ConstraintKind.LOWER) return@mapNotNull null - it.type.constructor.takeUnless { allTypeVariables.containsKey(it) } + it.type.typeConstructor().takeUnless { allTypeVariables.containsKey(it) } } } // ConstraintSystemBuilder - private fun transactionRegisterVariable(variable: NewTypeVariable) { + private fun transactionRegisterVariable(variable: TypeVariableMarker) { if (state != State.TRANSACTION) return typeVariablesTransaction.add(variable) } @@ -132,8 +136,8 @@ class NewConstraintSystemImpl( } for (addedTypeVariable in typeVariablesTransaction) { - storage.allTypeVariables.remove(addedTypeVariable.freshTypeConstructor) - storage.notFixedTypeVariables.remove(addedTypeVariable.freshTypeConstructor) + storage.allTypeVariables.remove(addedTypeVariable.freshTypeConstructor()) + storage.notFixedTypeVariables.remove(addedTypeVariable.freshTypeConstructor()) } storage.maxTypeDepthFromInitialConstraints = beforeMaxTypeDepthFromInitialConstraints storage.errors.trimToSize(beforeErrorsCount) @@ -169,32 +173,32 @@ class NewConstraintSystemImpl( } storage.initialConstraints.addAll(otherSystem.initialConstraints) storage.maxTypeDepthFromInitialConstraints = - Math.max(storage.maxTypeDepthFromInitialConstraints, otherSystem.maxTypeDepthFromInitialConstraints) + Math.max(storage.maxTypeDepthFromInitialConstraints, otherSystem.maxTypeDepthFromInitialConstraints) storage.errors.addAll(otherSystem.errors) storage.fixedTypeVariables.putAll(otherSystem.fixedTypeVariables) storage.postponedTypeVariables.addAll(otherSystem.postponedTypeVariables) } // ResultTypeResolver.Context, ConstraintSystemBuilder - override fun isProperType(type: UnwrappedType): Boolean { + override fun isProperType(type: KotlinTypeMarker): Boolean { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) 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) - 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) return typeVariable in postponedTypeVariables } // ConstraintInjector.Context - override val allTypeVariables: Map + override val allTypeVariables: Map get() { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) return storage.allTypeVariables @@ -213,19 +217,19 @@ class NewConstraintSystemImpl( } // ConstraintInjector.Context, FixationOrderCalculator.Context - override val notFixedTypeVariables: MutableMap + override val notFixedTypeVariables: MutableMap get() { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) return storage.notFixedTypeVariables } - override val fixedTypeVariables: MutableMap + override val fixedTypeVariables: MutableMap get() { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) return storage.fixedTypeVariables } - override val postponedTypeVariables: List + override val postponedTypeVariables: List get() { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) return storage.postponedTypeVariables @@ -238,32 +242,32 @@ class NewConstraintSystemImpl( } // KotlinConstraintSystemCompleter.Context - override fun fixVariable(variable: NewTypeVariable, resultType: UnwrappedType) { + override fun fixVariable(variable: TypeVariableMarker, resultType: KotlinTypeMarker) { checkState(State.BUILDING, State.COMPLETION) - constraintInjector.addInitialEqualityConstraint(this, variable.defaultType, resultType, FixVariableConstraintPosition(variable)) - notFixedTypeVariables.remove(variable.freshTypeConstructor) + constraintInjector.addInitialEqualityConstraint(this, variable.defaultType(), resultType, FixVariableConstraintPosition(variable)) + notFixedTypeVariables.remove(variable.freshTypeConstructor()) for (variableWithConstraint in notFixedTypeVariables.values) { 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 - override fun canBeProper(type: UnwrappedType): Boolean { + override fun canBeProper(type: KotlinTypeMarker): Boolean { 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) return !type.contains { - val variable = storage.notFixedTypeVariables[it.constructor]?.typeVariable - variable !in storage.postponedTypeVariables && storage.notFixedTypeVariables.containsKey(it.constructor) + val variable = storage.notFixedTypeVariables[it.typeConstructor()]?.typeVariable + variable !in storage.postponedTypeVariables && storage.notFixedTypeVariables.containsKey(it.typeConstructor()) } } @@ -273,14 +277,15 @@ class NewConstraintSystemImpl( return buildCurrentSubstitutor(emptyMap()) } - override fun buildCurrentSubstitutor(additionalBindings: Map): NewTypeSubstitutor { + override fun buildCurrentSubstitutor(additionalBindings: Map): NewTypeSubstitutor { checkState(State.BUILDING, State.COMPLETION) return storage.buildCurrentSubstitutor(additionalBindings) } - override fun bindingStubsForPostponedVariables(): Map { + override fun bindingStubsForPostponedVariables(): Map { 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 { @@ -289,10 +294,10 @@ class NewConstraintSystemImpl( } // PostponedArgumentsAnalyzer.Context - override fun hasUpperOrEqualUnitConstraint(type: UnwrappedType): Boolean { + override fun hasUpperOrEqualUnitConstraint(type: KotlinTypeMarker): Boolean { 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() } } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/TypeVariable.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/TypeVariable.kt index 0bbec1d3613..eab9ba6fd08 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/TypeVariable.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/TypeVariable.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.types.KotlinTypeFactory import org.jetbrains.kotlin.types.SimpleType import org.jetbrains.kotlin.types.TypeConstructor import org.jetbrains.kotlin.types.checker.NewTypeVariableConstructor +import org.jetbrains.kotlin.types.model.TypeVariableMarker 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)" } -sealed class NewTypeVariable(builtIns: KotlinBuiltIns, name: String) { +sealed class NewTypeVariable(builtIns: KotlinBuiltIns, name: String) : TypeVariableMarker { val freshTypeConstructor: TypeConstructor = TypeVariableTypeConstructor(builtIns, name) // member scope is used if we have receiver with type TypeVariable(T) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionCandidate.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionCandidate.kt index 389c4af98ea..60f07666be5 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionCandidate.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionCandidate.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.calls.model import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor 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.inference.NewConstraintSystem 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.tower.* import org.jetbrains.kotlin.types.TypeSubstitutor -import org.jetbrains.kotlin.types.UnwrappedType abstract class ResolutionPart { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt index 029b9180d0f..01909ae8685 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt @@ -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.FakeCallableDescriptorForTypeAliasObject import org.jetbrains.kotlin.resolve.calls.util.isLowPriorityFromStdlibJre7Or8 -import org.jetbrains.kotlin.resolve.descriptorUtil.HIDES_MEMBERS_NAME_LIST -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.descriptorUtil.* import org.jetbrains.kotlin.resolve.scopes.* import org.jetbrains.kotlin.resolve.scopes.receivers.CastImplicitClassReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver @@ -135,7 +132,7 @@ internal class MemberScopeTowerLevel( private fun CallableDescriptor.approximateCapturedTypes(): CallableDescriptor { if (!isNewInferenceEnabled) return this - val approximator = TypeApproximator() + val approximator = TypeApproximator(builtIns) val wrappedSubstitution = object : TypeSubstitution() { override fun get(key: KotlinType): TypeProjection? = null override fun prepareTopLevelType(topLevelType: KotlinType, position: Variance) = when (position) { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/types/TypeApproximator.kt b/compiler/resolution/src/org/jetbrains/kotlin/types/TypeApproximator.kt index e5cda6677f6..06980214553 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/types/TypeApproximator.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/types/TypeApproximator.kt @@ -16,19 +16,19 @@ package org.jetbrains.kotlin.types +import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings 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.constants.IntegerLiteralTypeConstructor import org.jetbrains.kotlin.types.TypeApproximatorConfiguration.IntersectionStrategy.* -import org.jetbrains.kotlin.types.checker.* -import org.jetbrains.kotlin.types.model.CaptureStatus +import org.jetbrains.kotlin.types.checker.NewCapturedType +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.typeUtil.asTypeProjection import org.jetbrains.kotlin.types.typeUtil.builtIns -import org.jetbrains.kotlin.types.typeUtil.isNothing -import org.jetbrains.kotlin.types.typeUtil.isNullableAny 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 { 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 // type <: resultType fun approximateToSuperType(type: UnwrappedType, conf: TypeApproximatorConfiguration): UnwrappedType? = - approximateToSuperType(type, conf, -type.typeDepth()) + super.approximateToSuperType(type, conf) as UnwrappedType? // resultType <: type 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()) - 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 return approximateTo( - NewKotlinTypeChecker.transformToNewType(type), conf, FlexibleType::upperBound, + prepareType(type), conf, { upperBound() }, 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 return approximateTo( - NewKotlinTypeChecker.transformToNewType(type), conf, FlexibleType::lowerBound, + prepareType(type), conf, { lowerBound() }, referenceApproximateToSubType, depth ) } // comments for case bound = upperBound, approximateTo = toSuperType private fun approximateTo( - type: UnwrappedType, + type: KotlinTypeMarker, conf: TypeApproximatorConfiguration, - bound: FlexibleType.() -> SimpleType, - approximateTo: (SimpleType, TypeApproximatorConfiguration, depth: Int) -> UnwrappedType?, + bound: FlexibleTypeMarker.() -> SimpleTypeMarker, + approximateTo: (SimpleTypeMarker, TypeApproximatorConfiguration, depth: Int) -> KotlinTypeMarker?, depth: Int - ): UnwrappedType? { + ): KotlinTypeMarker? { when (type) { - is SimpleType -> return approximateTo(type, conf, depth) - is FlexibleType -> { - if (type is DynamicType) { + is SimpleTypeMarker -> return approximateTo(type, conf, depth) + is FlexibleTypeMarker -> { + if (type.isDynamic()) { 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() } - // TODO: currently we can lose information about enhancement, should be fixed later - assert(type is FlexibleTypeImpl || type is FlexibleTypeWithEnhancement) { - "Unexpected subclass of FlexibleType: ${type::class.java.canonicalName}, type = $type" - } + // TODO: Restore check +// // TODO: currently we can lose information about enhancement, should be fixed later +// assert(type is FlexibleTypeImpl || type is FlexibleTypeWithEnhancement) { +// "Unexpected subclass of FlexibleType: ${type::class.java.canonicalName}, type = $type" +// } 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. */ - val lowerResult = approximateTo(type.lowerBound, conf, depth) - val upperResult = approximateTo(type.upperBound, conf, depth) + val lowerResult = approximateTo(type.lowerBound(), conf, depth) + val upperResult = approximateTo(type.upperBound(), conf, depth) 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. */ - return KotlinTypeFactory.flexibleType( - lowerResult?.lowerIfFlexible() ?: type.lowerBound, - upperResult?.upperIfFlexible() ?: type.upperBound + return createFlexibleType( + lowerResult?.lowerBoundIfFlexible() ?: type.lowerBound(), + upperResult?.upperBoundIfFlexible() ?: type.upperBound() ) } else { return type.bound().let { approximateTo(it, conf, depth) ?: it } } } + else -> error("sealed") } } private fun approximateIntersectionType( - type: SimpleType, + type: SimpleTypeMarker, conf: TypeApproximatorConfiguration, toSuper: Boolean, depth: Int - ): UnwrappedType? { - val typeConstructor = type.constructor - assert(typeConstructor is IntersectionTypeConstructor) { + ): KotlinTypeMarker? { + val typeConstructor = type.typeConstructor() + assert(typeConstructor.isIntersection()) { "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" } var thereIsApproximation = false - val newTypes = typeConstructor.supertypes.map { - val newType = if (toSuper) approximateToSuperType(it.unwrap(), conf, depth) else approximateToSubType(it.unwrap(), conf, depth) + val newTypes = typeConstructor.supertypes().map { + val newType = if (toSuper) approximateToSuperType(it, conf, depth) else approximateToSubType(it, conf, depth) if (newType != null) { thereIsApproximation = true newType - } else it.unwrap() + } else it } /** @@ -215,12 +233,12 @@ class TypeApproximator { // commonSupertypeCalculator should handle flexible types correctly TO_COMMON_SUPERTYPE -> { if (!toSuper) return type.defaultResult(toSuper = false) - val resultType = NewCommonSuperTypeCalculator.commonSuperType(newTypes) - approximateToSuperType(resultType.unwrap(), conf) ?: resultType.unwrap() + val resultType = with(NewCommonSuperTypeCalculator) { commonSuperType(newTypes) } + 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( @@ -228,30 +246,30 @@ class TypeApproximator { conf: TypeApproximatorConfiguration, toSuper: Boolean, depth: Int - ): UnwrappedType? { - val supertypes = type.constructor.supertypes + ): KotlinTypeMarker? { + val supertypes = type.typeConstructor().supertypes() val baseSuperType = when (supertypes.size) { 0 -> type.builtIns.nullableAnyType // Let C = in Int, then superType for C and C? is Any? 1 -> supertypes.single() - // Consider the following example: - // A.getA()::class.java, where `getA()` returns some class from Java - // From `::class` we are getting type KClass>, where Cap have two supertypes: - // - Any (from declared upper bound of type parameter for KClass) - // - (A..A?) -- from A!, projection type of captured type + // Consider the following example: + // A.getA()::class.java, where `getA()` returns some class from Java + // From `::class` we are getting type KClass>, where Cap have two supertypes: + // - Any (from declared upper bound of type parameter for KClass) + // - (A..A?) -- from A!, projection type of captured type - // Now, after approximation we were getting type `KClass`, because { Any & (A..A?) } = A, - // but in old inference type was equal to `KClass`. + // Now, after approximation we were getting type `KClass`, because { Any & (A..A?) } = A, + // but in old inference type was equal to `KClass`. - // Important note that from the point of type system first type is more specific: - // Here, approximation of KClass> is a type KClass such that KClass> <: KClass => - // 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` + // Important note that from the point of type system first type is more specific: + // Here, approximation of KClass> is a type KClass such that KClass> <: KClass => + // 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` + // But for now, to reduce differences in behaviour of old and new inference, we'll approximate such types to `KClass` - // 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 @@ -276,32 +294,38 @@ class TypeApproximator { // C = in Int, Int <: C => Int? <: C? // 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) - 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) - private fun approximateTo(type: SimpleType, conf: TypeApproximatorConfiguration, toSuper: Boolean, depth: Int): UnwrappedType? { - if (type.isError) { + private fun approximateTo( + type: SimpleTypeMarker, + conf: TypeApproximatorConfiguration, + toSuper: Boolean, + depth: Int + ): KotlinTypeMarker? { + if (type.isError()) { // todo -- fix builtIns. Now builtIns here is DefaultBuiltIns return if (conf.errorType) null else 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) } - if (type is DefinitelyNotNullType) { - return approximateDefinitelyNotNullType(type, conf, toSuper, depth) + val definitelyNotNullType = type.asDefinitelyNotNullType() + if (definitelyNotNullType != null) { + return approximateDefinitelyNotNullType(definitelyNotNullType, conf, toSuper, depth) } - val typeConstructor = type.constructor + val typeConstructor = type.typeConstructor() if (typeConstructor is NewCapturedTypeConstructor) { assert(type is NewCapturedType) { @@ -312,7 +336,7 @@ class TypeApproximator { return approximateCapturedType(type as NewCapturedType, conf, toSuper, depth) } - if (typeConstructor is IntersectionTypeConstructor) { + if (typeConstructor.isIntersection()) { return approximateIntersectionType(type, conf, toSuper, depth) } @@ -320,9 +344,9 @@ class TypeApproximator { return if (conf.typeVariable(typeConstructor)) null else type.defaultResult(toSuper) } - if (typeConstructor is IntegerLiteralTypeConstructor) { + if (typeConstructor.isIntegerLiteralTypeConstructor()) { return if (conf.integerLiteralType) - typeConstructor.getApproximatedType().unwrap().makeNullableAsSpecified(type.isMarkedNullable) + typeConstructor.getApproximatedIntegerLiteralType().withNullability(type.isMarkedNullable()) else null } @@ -331,63 +355,64 @@ class TypeApproximator { } private fun approximateDefinitelyNotNullType( - type: DefinitelyNotNullType, + type: DefinitelyNotNullTypeMarker, conf: TypeApproximatorConfiguration, toSuper: Boolean, depth: Int - ): UnwrappedType? { - val approximatedOriginalType = approximateTo(type.original, conf, toSuper, depth) + ): KotlinTypeMarker? { + val approximatedOriginalType = approximateTo(type.original(), conf, toSuper, depth) return if (conf.definitelyNotNullType) { approximatedOriginalType?.makeDefinitelyNotNullOrNotNull() } else { if (toSuper) - (approximatedOriginalType ?: type.original).makeNullableAsSpecified(false) + (approximatedOriginalType ?: type.original()).withNullability(false) else type.defaultResult(toSuper) } } - private fun isApproximateDirectionToSuper(effectiveVariance: Variance, toSuper: Boolean) = + private fun isApproximateDirectionToSuper(effectiveVariance: TypeVariance, toSuper: Boolean) = when (effectiveVariance) { - Variance.OUT_VARIANCE -> toSuper - Variance.IN_VARIANCE -> !toSuper - Variance.INVARIANT -> throw AssertionError("Incorrect variance $effectiveVariance") + TypeVariance.OUT -> toSuper + TypeVariance.IN -> !toSuper + TypeVariance.INV -> throw AssertionError("Incorrect variance $effectiveVariance") } private fun approximateParametrizedType( - type: SimpleType, + type: SimpleTypeMarker, conf: TypeApproximatorConfiguration, toSuper: Boolean, depth: Int - ): SimpleType? { - val parameters = type.constructor.parameters - val arguments = type.arguments - if (parameters.size != arguments.size) { + ): SimpleTypeMarker? { + val typeConstructor = type.typeConstructor() +// val parameters = type.typeConstructor().parameters +// val arguments = type.arguments + if (typeConstructor.parametersCount() != type.argumentsCount()) { 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) } - val newArguments = arrayOfNulls(arguments.size) + val newArguments = arrayOfNulls(type.argumentsCount()) - loop@ for (index in arguments.indices) { - val parameter = parameters[index] - val argument = arguments[index] + loop@ for (index in 0 until type.argumentsCount()) { + val parameter = typeConstructor.getParameter(index) + val argument = type.getArgument(index) - if (argument.isStarProjection) continue + if (argument.isStarProjection()) continue - val argumentType = argument.type.unwrap() - val effectiveVariance = NewKotlinTypeChecker.effectiveVariance(parameter.variance, argument.projectionKind) + val argumentType = argument.getType()//.unwrap() + val effectiveVariance = AbstractTypeChecker.effectiveVariance(parameter.getVariance(), argument.getVariance()) when (effectiveVariance) { null -> { return if (conf.errorType) { ErrorUtils.createErrorType( - "Inconsistent type: $type ($index parameter has declared variance: ${parameter.variance}, " + - "but argument variance is ${argument.projectionKind})" + "Inconsistent type: $type ($index parameter has declared variance: ${parameter.getVariance()}, " + + "but argument variance is ${argument.getVariance()})" ) } else type.defaultResult(toSuper) } - Variance.OUT_VARIANCE, Variance.IN_VARIANCE -> { + TypeVariance.OUT, TypeVariance.IN -> { /** * Out <: Out * Inv <: Inv @@ -403,22 +428,27 @@ class TypeApproximator { } } ?: continue@loop - if (parameter.variance == Variance.INVARIANT) { - newArguments[index] = TypeProjectionImpl(effectiveVariance, approximatedArgument) + if (parameter.getVariance() == TypeVariance.INV) { + newArguments[index] = createTypeArgument(approximatedArgument, effectiveVariance) } else { - newArguments[index] = approximatedArgument.asTypeProjection() + newArguments[index] = approximatedArgument.asTypeArgument() } } - Variance.INVARIANT -> { + TypeVariance.INV -> { if (!toSuper) { // Inv cannot be approximated to subType val toSubType = approximateToSubType(argumentType, conf, depth) ?: continue@loop // Inv is supertype for Inv - if (!NewKotlinTypeChecker.equalTypes(argumentType, toSubType)) return type.defaultResult(toSuper) + if (!AbstractTypeChecker.equalTypes( + this, + argumentType, + toSubType + ) + ) return type.defaultResult(toSuper) // also Captured(out Nothing) = Nothing - newArguments[index] = toSubType.asTypeProjection() + newArguments[index] = toSubType.asTypeArgument() continue@loop } @@ -433,10 +463,10 @@ class TypeApproximator { * Note that for case Inv we will chose Inv, because it is more informative then Inv. * 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 if (!subType.isTrivialSub()) { - newArguments[index] = TypeProjectionImpl(Variance.IN_VARIANCE, subType) + newArguments[index] = createTypeArgument(subType, TypeVariance.IN) continue@loop } } @@ -447,15 +477,15 @@ class TypeApproximator { val approximatedSubType = approximateToSubType(argumentType, conf, depth) ?: continue@loop // seems like this is never null if (!approximatedSubType.isTrivialSub()) { - newArguments[index] = TypeProjectionImpl(Variance.IN_VARIANCE, approximatedSubType) + newArguments[index] = createTypeArgument(approximatedSubType, TypeVariance.IN) continue@loop } } - if (NewKotlinTypeChecker.equalTypes(argumentType, approximatedSuperType)) { - newArguments[index] = approximatedSuperType.asTypeProjection() + if (AbstractTypeChecker.equalTypes(this, argumentType, approximatedSuperType)) { + newArguments[index] = approximatedSuperType.asTypeArgument() } 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 - val newArgumentsList = arguments.mapIndexed { index, oldArgument -> newArguments[index] ?: oldArgument } - return type.replace(newArgumentsList) + val newArgumentsList = List(type.argumentsCount()) { index -> newArguments[index] ?: type.getArgument(index) } + return type.replaceArguments(newArgumentsList) } - private fun SimpleType.defaultResult(toSuper: Boolean) = if (toSuper) builtIns.nullableAnyType else { - if (isMarkedNullable) builtIns.nullableNothingType else builtIns.nothingType + private fun SimpleTypeMarker.defaultResult(toSuper: Boolean) = if (toSuper) nullableAnyType() else { + if (isMarkedNullable()) nullableNothingType() else nothingType() } // Any? or Any! - private fun UnwrappedType.isTrivialSuper() = upperIfFlexible().isNullableAny() + private fun KotlinTypeMarker.isTrivialSuper() = upperBoundIfFlexible().isNullableAny() // Nothing or Nothing! - private fun UnwrappedType.isTrivialSub() = lowerIfFlexible().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 + private fun KotlinTypeMarker.isTrivialSub() = lowerBoundIfFlexible().isNothing() } +// +//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 +//} diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/StubType.kt b/core/descriptors/src/org/jetbrains/kotlin/types/StubType.kt index 522fa24636a..414873adbaa 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/StubType.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/StubType.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.types import org.jetbrains.kotlin.descriptors.annotations.Annotations 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 class StubType( @@ -16,7 +17,7 @@ class StubType( ErrorUtils.createErrorTypeConstructor("Constructor for non fixed type: $originalTypeVariable"), override val memberScope: MemberScope = ErrorUtils.createErrorScope("Scope for non fixed type: $originalTypeVariable") -) : SimpleType() { +) : SimpleType(), StubTypeMarker { override val arguments: List get() = emptyList() diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeCheckerContext.kt b/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeCheckerContext.kt index 357a6635fb1..18ba91b4414 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeCheckerContext.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeCheckerContext.kt @@ -24,13 +24,9 @@ import org.jetbrains.kotlin.types.model.SimpleTypeMarker import org.jetbrains.kotlin.types.model.TypeConstructorMarker open class ClassicTypeCheckerContext(val errorTypeEqualsToAnything: Boolean, val allowedTypeVariable: Boolean = true) : ClassicTypeSystemContext, AbstractTypeCheckerContext() { - override fun intersectTypes(types: List): KotlinTypeMarker { - @Suppress("UNCHECKED_CAST") - return org.jetbrains.kotlin.types.checker.intersectTypes(types as List) - } override fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker { - return super.prepareType(transformToNewType((type as KotlinType).unwrap())) + return transformToNewType((type as KotlinType).unwrap()) } override val isErrorTypeEqualsToAnything: Boolean @@ -54,22 +50,26 @@ open class ClassicTypeCheckerContext(val errorTypeEqualsToAnything: Boolean, val } 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() { - override fun transformType(context: AbstractTypeCheckerContext, type: KotlinTypeMarker): SimpleTypeMarker { - return substitutor.safeSubstitute( - type.lowerBoundIfFlexible() as KotlinType, - Variance.INVARIANT - ).asSimpleType()!! + companion object { + fun ClassicTypeSystemContext.classicSubstitutionSupertypePolicy(type: SimpleTypeMarker): SupertypesPolicy.DoCustomTransform { + require(type is SimpleType, type::errorMessage) + val substitutor = TypeConstructorSubstitution.create(type).buildSubstitutor() + + 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 { diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt b/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt index 7a97acf3995..4bb4735fa2e 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt @@ -8,14 +8,18 @@ package org.jetbrains.kotlin.types.checker import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES 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.descriptorUtil.hasExactAnnotation +import org.jetbrains.kotlin.resolve.descriptorUtil.hasNoInferAnnotation import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.model.* import org.jetbrains.kotlin.types.model.CaptureStatus 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 { require(this is TypeConstructor, this::errorMessage) 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 { require(this is TypeProjection, this::errorMessage) @@ -220,6 +231,11 @@ interface ClassicTypeSystemContext : TypeSystemContext { 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: @@ -240,6 +256,231 @@ interface ClassicTypeSystemContext : TypeSystemContext { require(this is KotlinType, this::errorMessage) 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 { + @Suppress("UNCHECKED_CAST") + return org.jetbrains.kotlin.types.checker.intersectTypes(types as List) + } + + override fun intersectTypes(types: List): SimpleTypeMarker { + @Suppress("UNCHECKED_CAST") + return org.jetbrains.kotlin.types.checker.intersectTypes(types as List) + } + + override fun Collection.singleBestRepresentative(): KotlinTypeMarker? { + @Suppress("UNCHECKED_CAST") + return singleBestRepresentative(this as Collection) + } + + 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, + nullable: Boolean + ): SimpleTypeMarker { + require(constructor is TypeConstructor, constructor::errorMessage) + @Suppress("UNCHECKED_CAST") + return KotlinTypeFactory.simpleType(Annotations.EMPTY, constructor, arguments as List, 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): SimpleTypeMarker { + require(this is SimpleType, this::errorMessage) + return this.replace(newArguments as List) + } + + 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, + lowerType: KotlinTypeMarker?, + captureStatus: CaptureStatus + ): CapturedTypeMarker { + errorSupportedOnlyInTypeInference() + } + + override fun typeSubstitutorByTypeConstructor(map: Map): 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? { + @Suppress("UNCHECKED_CAST") + explicitSupertypes as List + 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) = 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}" } +private fun errorSupportedOnlyInTypeInference(): Nothing { + error("supported only in type inference context") +} + fun Variance.convertVariance(): TypeVariance { return when (this) { Variance.INVARIANT -> TypeVariance.INV diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewKotlinTypeChecker.kt b/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewKotlinTypeChecker.kt index 107a3d31048..6d628074733 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewKotlinTypeChecker.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewKotlinTypeChecker.kt @@ -30,20 +30,21 @@ import org.jetbrains.kotlin.types.model.CaptureStatus import org.jetbrains.kotlin.types.typeUtil.* import org.jetbrains.kotlin.utils.addToStdlib.cast +object SimpleClassicTypeSystemContext : ClassicTypeSystemContext + object StrictEqualityTypeChecker { - private val context = object : ClassicTypeSystemContext {} /** * String! != String & A != A, also A != A * also A<*> != A * different error types non-equals even errorTypeEqualToAnything */ 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 { - 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()) 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 { - return AbstractTypeChecker.isSubtypeOf(this, subType, superType) + return AbstractTypeChecker.isSubtypeOf(this as AbstractTypeCheckerContext, subType, superType) } fun transformToNewType(type: SimpleType): SimpleType { @@ -156,10 +157,9 @@ object NewKotlinTypeChecker : KotlinTypeChecker { object NullabilityChecker { fun isSubtypeOfAny(type: UnwrappedType): Boolean = - ClassicTypeCheckerContext(false).hasNotNullSupertype(type.lowerIfFlexible(), SupertypesPolicy.LowerIfFlexible) - - fun hasPathByNotMarkedNullableNodes(start: SimpleType, end: TypeConstructor) = - ClassicTypeCheckerContext(false).hasPathByNotMarkedNullableNodes(start, end) + SimpleClassicTypeSystemContext + .newBaseTypeCheckerContext(false) + .hasNotNullSupertype(type.lowerIfFlexible(), SupertypesPolicy.LowerIfFlexible) } fun UnwrappedType.hasSupertypeWithGivenTypeConstructor(typeConstructor: TypeConstructor) = diff --git a/core/type-system/src/org/jetbrains/kotlin/types/AbstractTypeChecker.kt b/core/type-system/src/org/jetbrains/kotlin/types/AbstractTypeChecker.kt index 58dac4c1b07..3c78abf7f63 100644 --- a/core/type-system/src/org/jetbrains/kotlin/types/AbstractTypeChecker.kt +++ b/core/type-system/src/org/jetbrains/kotlin/types/AbstractTypeChecker.kt @@ -21,9 +21,7 @@ abstract class AbstractTypeCheckerContext : TypeSystemContext { abstract fun areEqualTypeConstructors(a: TypeConstructorMarker, b: TypeConstructorMarker): Boolean - abstract fun intersectTypes(types: List): KotlinTypeMarker - - open fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker { + override fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker { return type } @@ -146,6 +144,15 @@ abstract class AbstractTypeCheckerContext : TypeSystemContext { } 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 { if (subType === superType) return true return context.completeIsSubTypeOf(context.prepareType(subType), context.prepareType(superType)) @@ -312,7 +319,7 @@ object AbstractTypeChecker { !type.isDynamic() && !type.isDefinitelyNotNullType() && 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 (useSite == TypeVariance.INV) return declared @@ -453,6 +460,14 @@ object AbstractNullabilityChecker { fun isPossibleSubtype(context: AbstractTypeCheckerContext, subType: SimpleTypeMarker, superType: SimpleTypeMarker): Boolean = 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 { // it makes for case String? & Any <: String assert(subType.isSingleClassifierType() || subType.typeConstructor().isIntersection() || subType.isAllowedTypeVariable) { @@ -501,6 +516,9 @@ object AbstractNullabilityChecker { 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) = anySupertype(start, { it.isNotNullNothing() || (!it.isMarkedNullable() && isEqualTypeConstructors(it.typeConstructor(), end)) diff --git a/core/type-system/src/org/jetbrains/kotlin/types/model/MarkerExtensions.kt b/core/type-system/src/org/jetbrains/kotlin/types/model/MarkerExtensions.kt new file mode 100644 index 00000000000..a106cbcba50 --- /dev/null +++ b/core/type-system/src/org/jetbrains/kotlin/types/model/MarkerExtensions.kt @@ -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() } \ No newline at end of file diff --git a/core/type-system/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt b/core/type-system/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt index ad0a07c9a98..e1018cbcd38 100644 --- a/core/type-system/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt +++ b/core/type-system/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt @@ -5,6 +5,8 @@ package org.jetbrains.kotlin.types.model +import org.jetbrains.kotlin.types.AbstractTypeCheckerContext + interface KotlinTypeMarker interface TypeArgumentMarker interface TypeConstructorMarker @@ -17,14 +19,21 @@ interface DefinitelyNotNullTypeMarker : SimpleTypeMarker interface FlexibleTypeMarker : KotlinTypeMarker interface DynamicTypeMarker : FlexibleTypeMarker interface RawTypeMarker : FlexibleTypeMarker +interface StubTypeMarker : SimpleTypeMarker interface TypeArgumentListMarker +interface TypeVariableMarker -enum class TypeVariance { - IN, - OUT, - INV +interface TypeSubstitutorMarker + + +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 } +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, 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? +} + +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.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, + lowerType: KotlinTypeMarker?, + captureStatus: CaptureStatus + ): CapturedTypeMarker + + fun createStubType(typeVariable: TypeVariableMarker): StubTypeMarker + + + fun KotlinTypeMarker.removeAnnotations(): KotlinTypeMarker + + fun SimpleTypeMarker.replaceArguments(newArguments: List): 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): TypeSubstitutorMarker + + fun TypeSubstitutorMarker.safeSubstitute(type: KotlinTypeMarker): KotlinTypeMarker + + + fun TypeVariableMarker.defaultType(): SimpleTypeMarker +} + class ArgumentList(initialSize: Int) : ArrayList(initialSize), TypeArgumentListMarker @@ -53,6 +152,8 @@ interface TypeSystemContext : TypeSystemOptimizationContext { fun FlexibleTypeMarker.lowerBound(): SimpleTypeMarker fun SimpleTypeMarker.asCapturedType(): CapturedTypeMarker? + fun KotlinTypeMarker.isCapturedType() = asSimpleType()?.asCapturedType() != null + fun SimpleTypeMarker.asDefinitelyNotNullType(): DefinitelyNotNullTypeMarker? fun SimpleTypeMarker.isMarkedNullable(): Boolean fun SimpleTypeMarker.withNullability(nullable: Boolean): SimpleTypeMarker @@ -66,7 +167,7 @@ interface TypeSystemContext : TypeSystemOptimizationContext { return null } - fun SimpleTypeMarker.isStubType(): Boolean = false + fun SimpleTypeMarker.isStubType(): Boolean 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 */ fun SimpleTypeMarker.isSingleClassifierType(): Boolean + + fun intersectTypes(types: List): KotlinTypeMarker + fun intersectTypes(types: List): SimpleTypeMarker + + fun KotlinTypeMarker.isSimpleType() = asSimpleType() != null + + fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker } enum class CaptureStatus { diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt index 60ac96dee40..fd1f764d08a 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt @@ -44,7 +44,7 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.* val BackendContext.externalSymbols: ReferenceSymbolTable get() = ir.symbols.externalSymbolTable 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.typeTranslator = this } diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinInternalUastUtils.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinInternalUastUtils.kt index 94c9d4e897c..d9c5c2c3b73 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinInternalUastUtils.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinInternalUastUtils.kt @@ -57,6 +57,7 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ import org.jetbrains.kotlin.synthetic.SamAdapterExtensionFunctionDescriptor import org.jetbrains.kotlin.type.MapPsiToAsmDesc import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.types.typeUtil.builtIns import org.jetbrains.kotlin.types.typeUtil.isInterface import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.uast.* @@ -232,7 +233,7 @@ internal fun KotlinType.toPsiType(lightDeclaration: PsiModifierListOwner?, conte val signatureWriter = BothSignatureWriter(BothSignatureWriter.Mode.TYPE) 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) val signature = StringCharacterIterator(signatureWriter.toString())