From 3998e842f15db108ee8f20a075b22285e46716a6 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Mon, 18 Feb 2019 20:19:33 +0300 Subject: [PATCH] Abstract NewInference & related from KotlinType Cleanup TypeConstructors & KotlinTypes in VariableFixationFinder Cleanup TypeConstructors & KotlinTypes in TypeVariableDirectionCalculator Cleanup KotlinTypes in TypeCheckerContext for ConstraintSystem Cleanup KotlinTypes in NewCommonSuperTypeCalculator Cleanup KotlinTypes in TypeApproximator Cleanup type substitution Cleanup NewTypeVariable Cleanup StubType Cleanup TypeCheckerContext creation, extract common supertype context Provide TypeSystemInferenceExtensionContext via dependency injection --- .../kotlin/fir/types/ConeTypeContext.kt | 21 ++ .../jetbrains/kotlin/frontend/di/injection.kt | 2 + .../DiagnosticReporterByTrackingStrategy.kt | 15 +- .../inference/CoroutineInferenceSession.kt | 12 +- .../tower/KotlinToResolvedCallTransformer.kt | 4 +- .../calls/tower/ResolvedAtomCompleter.kt | 2 +- .../jvm/lower/JvmCoercionToUnitPatcher.kt | 2 +- .../psi2ir/generators/GeneratorContext.kt | 2 +- .../ir/util/DeclarationStubGenerator.kt | 2 +- .../kotlin/ir/util/TypeTranslator.kt | 10 +- .../calls/NewCommonSuperTypeCalculator.kt | 153 ++++++---- .../calls/components/BuiltInsProvider.kt | 19 ++ .../ClassicTypeSystemContextForCS.kt | 87 ++++++ .../calls/components/KotlinCallCompleter.kt | 7 +- .../components/PostponeArgumentsChecks.kt | 19 +- .../components/PostponedArgumentsAnalyzer.kt | 20 +- .../inference/ConstraintSystemBuilder.kt | 28 +- .../resolve/calls/inference/InferenceUtils.kt | 14 +- .../calls/inference/NewConstraintSystem.kt | 2 +- ...tTypeCheckerContextForConstraintSystem.kt} | 150 +++++----- .../components/ConstraintIncorporator.kt | 135 +++++---- .../components/ConstraintInjector.kt | 100 ++++--- .../KotlinConstraintSystemCompleter.kt | 16 +- .../components/NewTypeSubstitutor.kt | 3 +- .../components/ResultTypeResolver.kt | 56 ++-- .../components/SimpleConstraintSystemImpl.kt | 4 +- .../TrivialConstraintTypeInferenceOracle.kt | 40 +-- ...peVariableDependencyInformationProvider.kt | 51 ++-- .../TypeVariableDirectionCalculator.kt | 64 ++-- .../components/VariableFixationFinder.kt | 37 +-- .../model/ConstraintPositionAndErrors.kt | 18 +- .../inference/model/ConstraintStorage.kt | 46 +-- .../model/MutableConstraintStorage.kt | 13 +- .../model/NewConstraintSystemImpl.kt | 97 +++--- .../calls/inference/model/TypeVariable.kt | 3 +- .../calls/model/ResolutionCandidate.kt | 2 +- .../kotlin/resolve/calls/tower/TowerLevels.kt | 7 +- .../kotlin/types/TypeApproximator.kt | 282 ++++++++++-------- .../org/jetbrains/kotlin/types/StubType.kt | 3 +- .../checker/ClassicTypeCheckerContext.kt | 32 +- .../types/checker/ClassicTypeSystemContext.kt | 247 ++++++++++++++- .../types/checker/NewKotlinTypeChecker.kt | 18 +- .../kotlin/types/AbstractTypeChecker.kt | 26 +- .../kotlin/types/model/MarkerExtensions.kt | 14 + .../kotlin/types/model/TypeSystemContext.kt | 118 +++++++- .../compiler/backend/ir/GeneratorHelpers.kt | 2 +- .../internal/kotlinInternalUastUtils.kt | 3 +- 47 files changed, 1347 insertions(+), 661 deletions(-) create mode 100644 compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/BuiltInsProvider.kt create mode 100644 compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ClassicTypeSystemContextForCS.kt rename compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/{TypeCheckerContextForConstraintSystem.kt => AbstractTypeCheckerContextForConstraintSystem.kt} (53%) create mode 100644 core/type-system/src/org/jetbrains/kotlin/types/model/MarkerExtensions.kt 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())