diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyInferenceSession.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyInferenceSession.kt index 24d969e6077..55eb8543539 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyInferenceSession.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyInferenceSession.kt @@ -9,16 +9,14 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors -import org.jetbrains.kotlin.resolve.calls.components.ErrorCallInfo -import org.jetbrains.kotlin.resolve.calls.components.InferenceSession -import org.jetbrains.kotlin.resolve.calls.components.PartialCallInfo -import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer +import org.jetbrains.kotlin.resolve.calls.components.* import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage import org.jetbrains.kotlin.resolve.calls.inference.model.DelegatedPropertyConstraintPosition import org.jetbrains.kotlin.resolve.calls.inference.model.ExpectedTypeConstraintPosition +import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable import org.jetbrains.kotlin.resolve.calls.model.KotlinCallComponents import org.jetbrains.kotlin.resolve.calls.model.KotlinResolutionCandidate import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallAtom @@ -26,6 +24,7 @@ import org.jetbrains.kotlin.resolve.calls.tower.ManyCandidatesResolver import org.jetbrains.kotlin.resolve.calls.tower.PSICallResolver import org.jetbrains.kotlin.resolve.calls.tower.PSIPartialCallInfo import org.jetbrains.kotlin.types.ErrorUtils +import org.jetbrains.kotlin.types.TypeConstructor import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.util.OperatorNameConventions @@ -83,6 +82,8 @@ class DelegatedPropertyInferenceSession( addConstraintForThis(candidateDescriptor, commonSystem) } + + override fun inferPostponedVariables(initialStorage: ConstraintStorage): Map = emptyMap() } object InferenceSessionForExistingCandidates : InferenceSession { @@ -91,9 +92,9 @@ object InferenceSessionForExistingCandidates : InferenceSession { } override fun addPartialCallInfo(callInfo: PartialCallInfo) {} + override fun addCompletedCallInfo(callInfo: CompletedCallInfo) {} override fun addErrorCallInfo(callInfo: ErrorCallInfo) {} - override fun currentConstraintSystem(): ConstraintStorage { - return ConstraintStorage.Empty - } + override fun currentConstraintSystem(): ConstraintStorage = ConstraintStorage.Empty + override fun inferPostponedVariables(initialStorage: ConstraintStorage): Map = emptyMap() } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/context/ResolutionContext.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/context/ResolutionContext.java index 9410949d586..22a3e73aeaf 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/context/ResolutionContext.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/context/ResolutionContext.java @@ -145,6 +145,14 @@ public abstract class ResolutionContext, + private val trace: BindingTrace, + private val kotlinToResolvedCallTransformer: KotlinToResolvedCallTransformer +) : ManyCandidatesResolver( + psiCallResolver, postponedArgumentsAnalyzer, kotlinConstraintSystemCompleter, callComponents, builtIns +) { + private val suspendCompletedCalls = arrayListOf() + private val normalCompletedCalls = arrayListOf() + + override fun shouldRunCompletion(candidate: KotlinResolutionCandidate): Boolean = true + + override fun addCompletedCallInfo(callInfo: CompletedCallInfo) { + require(callInfo is PSICompletedCallInfo) { "Wrong instance of callInfo: $callInfo" } + + val candidateDescriptor = callInfo.callResolutionResult.resultCallAtom.candidateDescriptor + if (candidateDescriptor is FunctionDescriptor && candidateDescriptor.isSuspend) + suspendCompletedCalls.add(callInfo) + else + normalCompletedCalls.add(callInfo) + } + + override fun currentConstraintSystem(): ConstraintStorage { + return ConstraintStorage.Empty + } + + override fun inferPostponedVariables(initialStorage: ConstraintStorage): Map { + val commonSystem = buildCommonSystem(initialStorage) + + val context = commonSystem.asConstraintSystemCompleterContext() + kotlinConstraintSystemCompleter.completeConstraintSystem(context, builtIns.unitType) + + updateCalls(initialStorage, commonSystem) + + return commonSystem.fixedTypeVariables + } + + private fun createNonFixedTypeToVariableSubstitutor(): NewTypeSubstitutorByConstructorMap { + val bindings = hashMapOf() + for ((variable, nonFixedType) in stubsForPostponedVariables) { + bindings[nonFixedType.constructor] = variable.defaultType + } + + return NewTypeSubstitutorByConstructorMap(bindings) + } + + private fun integrateConstraints( + commonSystem: NewConstraintSystemImpl, + storage: ConstraintStorage, + nonFixedToVariablesSubstitutor: NewTypeSubstitutor + ) { + storage.notFixedTypeVariables.values.forEach { commonSystem.registerVariable(it.typeVariable) } + + /* + * storage can contain the following substitutions: + * TypeVariable(A) -> ProperType + * TypeVariable(B) -> Special-Non-Fixed-Type + * + * while substitutor from parameter map non-fixed types to the original type variable + * */ + val callSubstitutor = storage.buildResultingSubstitutor() + + for (initialConstraint in storage.initialConstraints) { + val lower = nonFixedToVariablesSubstitutor.safeSubstitute(callSubstitutor.safeSubstitute(initialConstraint.a)) + val upper = nonFixedToVariablesSubstitutor.safeSubstitute(callSubstitutor.safeSubstitute(initialConstraint.b)) + + if (commonSystem.isProperType(lower) && commonSystem.isProperType(upper)) continue + + when (initialConstraint.constraintKind) { + ConstraintKind.LOWER -> error("LOWER constraint shouldn't be used, please use UPPER") + + ConstraintKind.UPPER -> commonSystem.addSubtypeConstraint(lower, upper, initialConstraint.position) + + ConstraintKind.EQUALITY -> + with(commonSystem) { + addSubtypeConstraint(lower, upper, initialConstraint.position) + addSubtypeConstraint(upper, lower, initialConstraint.position) + } + } + } + } + + private fun buildCommonSystem(initialStorage: ConstraintStorage): NewConstraintSystemImpl { + val commonSystem = NewConstraintSystemImpl(callComponents.constraintInjector, builtIns) + + val nonFixedToVariablesSubstitutor = createNonFixedTypeToVariableSubstitutor() + + integrateConstraints(commonSystem, initialStorage, nonFixedToVariablesSubstitutor) + + for (suspendCall in suspendCompletedCalls) { + integrateConstraints(commonSystem, suspendCall.callResolutionResult.constraintSystem, nonFixedToVariablesSubstitutor) + } + + return commonSystem + } + + private fun updateCalls(initialStorage: ConstraintStorage, commonSystem: NewConstraintSystemImpl) { + val nonFixedToResult = mutableMapOf() + for (variable in initialStorage.postponedTypeVariables) { + nonFixedToResult[variable.freshTypeConstructor] = commonSystem.fixedTypeVariables[variable.freshTypeConstructor] ?: continue + } + + val commonSystemSubstitutor = NewTypeSubstitutorByConstructorMap(nonFixedToResult) + + for (completedCall in suspendCompletedCalls + normalCompletedCalls) { + val resultCallAtom = completedCall.callResolutionResult.resultCallAtom + val call = resultCallAtom.atom.getResolvedPsiKotlinCall(trace) ?: continue + + val resultingCallSubstitutor = completedCall + .callResolutionResult + .constraintSystem + .fixedTypeVariables + .entries + .associate { it.key to commonSystemSubstitutor.safeSubstitute(it.value) } + + call.setResultingSubstitutor(NewTypeSubstitutorByConstructorMap(resultingCallSubstitutor)) + + val resultingDescriptor = call.resultingDescriptor + kotlinToResolvedCallTransformer.reportCallDiagnostic( + completedCall.context, trace, resultCallAtom, resultingDescriptor, commonSystem.diagnostics + ) + } + } +} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt index 8cac37c8d37..6f48b2f734c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt @@ -23,7 +23,11 @@ import org.jetbrains.kotlin.resolve.TypeResolver import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver import org.jetbrains.kotlin.resolve.calls.components.InferenceSession import org.jetbrains.kotlin.resolve.calls.components.KotlinResolutionCallbacks +import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer import org.jetbrains.kotlin.resolve.calls.context.ContextDependency +import org.jetbrains.kotlin.resolve.calls.inference.CoroutineInferenceSession +import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter +import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory @@ -33,10 +37,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo -import org.jetbrains.kotlin.types.TypeApproximator -import org.jetbrains.kotlin.types.TypeApproximatorConfiguration -import org.jetbrains.kotlin.types.TypeUtils -import org.jetbrains.kotlin.types.UnwrappedType +import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo import org.jetbrains.kotlin.types.typeUtil.isUnit @@ -60,7 +61,11 @@ class KotlinResolutionCallbacksImpl( val dataFlowValueFactory: DataFlowValueFactory, override val inferenceSession: InferenceSession, val constantExpressionEvaluator: ConstantExpressionEvaluator, - val typeResolver: TypeResolver + val typeResolver: TypeResolver, + val psiCallResolver: PSICallResolver, + val postponedArgumentsAnalyzer: PostponedArgumentsAnalyzer, + val kotlinConstraintSystemCompleter: KotlinConstraintSystemCompleter, + val callComponents: KotlinCallComponents ) : KotlinResolutionCallbacks { class LambdaInfo(val expectedType: UnwrappedType, val contextDependency: ContextDependency) { val returnStatements = ArrayList>() @@ -76,8 +81,9 @@ class KotlinResolutionCallbacksImpl( isSuspend: Boolean, receiverType: UnwrappedType?, parameters: List, - expectedReturnType: UnwrappedType? - ): List { + expectedReturnType: UnwrappedType?, + stubsForPostponedVariables: Map + ): Pair, InferenceSession?> { val psiCallArgument = lambdaArgument.psiCallArgument as PSIFunctionKotlinCallArgument val outerCallContext = psiCallArgument.outerCallContext @@ -122,11 +128,22 @@ class KotlinResolutionCallbacksImpl( val approximatesExpectedType = typeApproximator.approximateToSubType(expectedType, TypeApproximatorConfiguration.LocalDeclaration) ?: expectedType + val coroutineSession = + if (stubsForPostponedVariables.isNotEmpty()) + CoroutineInferenceSession( + psiCallResolver, postponedArgumentsAnalyzer, kotlinConstraintSystemCompleter, + callComponents, builtIns, stubsForPostponedVariables, trace, kotlinToResolvedCallTransformer + ) + else + null + val actualContext = outerCallContext .replaceBindingTrace(trace) .replaceContextDependency(lambdaInfo.contextDependency) .replaceExpectedType(approximatesExpectedType) - .replaceDataFlowInfo(psiCallArgument.lambdaInitialDataFlowInfo) + .replaceDataFlowInfo(psiCallArgument.lambdaInitialDataFlowInfo).let { + if (coroutineSession != null) it.replaceInferenceSession(coroutineSession) else it + } val functionTypeInfo = expressionTypingServices.getTypeInfo(psiCallArgument.expression, actualContext) trace.record(BindingContext.NEW_INFERENCE_LAMBDA_INFO, psiCallArgument.ktFunction, LambdaInfo.STUB_EMPTY) @@ -159,7 +176,7 @@ class KotlinResolutionCallbacksImpl( returnArguments.addIfNotNull(lastExpressionArgument) - return returnArguments + return Pair(returnArguments, coroutineSession) } private fun getLastDeparentesizedExpression(psiCallArgument: PSIKotlinCallArgument): KtExpression? { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionStatelessCallbacksImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionStatelessCallbacksImpl.kt index 539532b60b4..16c5e4b3c76 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionStatelessCallbacksImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionStatelessCallbacksImpl.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.resolve.calls.tower import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.psi.KtSuperExpression import org.jetbrains.kotlin.resolve.DeprecationResolver import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils @@ -25,8 +26,10 @@ import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isConventionCall import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isInfixCall import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isSuperOrDelegatingConstructorCall import org.jetbrains.kotlin.resolve.calls.components.KotlinResolutionStatelessCallbacks +import org.jetbrains.kotlin.resolve.calls.inference.isCoroutineCallWithAdditionalInference import org.jetbrains.kotlin.resolve.calls.model.CallableReferenceKotlinCallArgument import org.jetbrains.kotlin.resolve.calls.model.KotlinCall +import org.jetbrains.kotlin.resolve.calls.model.KotlinCallArgument import org.jetbrains.kotlin.resolve.calls.model.SimpleKotlinCallArgument import org.jetbrains.kotlin.utils.addToStdlib.safeAs @@ -57,4 +60,7 @@ class KotlinResolutionStatelessCallbacksImpl( override fun getVariableCandidateIfInvoke(functionCall: KotlinCall) = functionCall.safeAs()?.variableCall + + override fun isCoroutineCall(argument: KotlinCallArgument, parameter: ValueParameterDescriptor): Boolean = + isCoroutineCallWithAdditionalInference(parameter, argument.psiCallArgument.valueArgument) } 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 3ffdf4c74f3..2181960052f 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 @@ -96,6 +96,10 @@ class KotlinToResolvedCallTransformer( is CompletedCallResolutionResult, is ErrorCallResolutionResult -> { val candidate = (baseResolvedCall as SingleCallResolutionResult).resultCallAtom + context.inferenceSession.addCompletedCallInfo( + PSICompletedCallInfo(baseResolvedCall as CompletedCallResolutionResult, context, tracingStrategy) + ) + val resultSubstitutor = baseResolvedCall.constraintSystem.buildResultingSubstitutor() val ktPrimitiveCompleter = ResolvedAtomCompleter( resultSubstitutor, context.trace, context, this, expressionTypingServices, argumentTypeResolver, @@ -153,8 +157,7 @@ class KotlinToResolvedCallTransformer( diagnostics: Collection ): NewResolvedCallImpl { if (trace != null) { - val storedResolvedCall = - completedSimpleAtom.atom.psiKotlinCall.psiCall.getResolvedCall(trace.bindingContext)?.safeAs>() + val storedResolvedCall = completedSimpleAtom.atom.psiKotlinCall.getResolvedPsiKotlinCall(trace) if (storedResolvedCall != null) { storedResolvedCall.setResultingSubstitutor(resultSubstitutor) storedResolvedCall.updateDiagnostics(diagnostics) @@ -339,7 +342,7 @@ class KotlinToResolvedCallTransformer( reportCallDiagnostic(context, trace, functionCall.resolvedCallAtom, functionCall.resultingDescriptor, emptyList()) } - private fun reportCallDiagnostic( + fun reportCallDiagnostic( context: BasicCallResolutionContext, trace: BindingTrace, completedCallAtom: ResolvedCallAtom, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ManyCandidatesResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ManyCandidatesResolver.kt index 9f0a64617d5..f5b7de9b60b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ManyCandidatesResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ManyCandidatesResolver.kt @@ -7,28 +7,31 @@ package org.jetbrains.kotlin.resolve.calls.tower import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.CallableDescriptor -import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.calls.components.* import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl +import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy +import org.jetbrains.kotlin.types.TypeConstructor abstract class ManyCandidatesResolver( private val psiCallResolver: PSICallResolver, private val postponedArgumentsAnalyzer: PostponedArgumentsAnalyzer, - private val kotlinConstraintSystemCompleter: KotlinConstraintSystemCompleter, - private val callComponents: KotlinCallComponents, + protected val kotlinConstraintSystemCompleter: KotlinConstraintSystemCompleter, + protected val callComponents: KotlinCallComponents, val builtIns: KotlinBuiltIns ) : InferenceSession { private val partiallyResolvedCallsInfo = arrayListOf() private val errorCallsInfo = arrayListOf>() - abstract fun prepareForCompletion(commonSystem: NewConstraintSystem, resolvedCallsInfo: List) + open fun prepareForCompletion(commonSystem: NewConstraintSystem, resolvedCallsInfo: List) { + // do nothing + } override fun shouldRunCompletion(candidate: KotlinResolutionCandidate): Boolean { return false @@ -41,6 +44,10 @@ abstract class ManyCandidatesResolver( partiallyResolvedCallsInfo.add(callInfo) } + override fun addCompletedCallInfo(callInfo: CompletedCallInfo) { + // do nothing + } + override fun addErrorCallInfo(callInfo: ErrorCallInfo) { if (callInfo !is PSIErrorCallInfo<*>) { throw AssertionError("Error call info for $callInfo should be instance of PSIErrorCallInfo") @@ -108,6 +115,12 @@ class PSIPartialCallInfo( val tracingStrategy: TracingStrategy ) : PartialCallInfo +class PSICompletedCallInfo( + override val callResolutionResult: CompletedCallResolutionResult, + val context: BasicCallResolutionContext, + val tracingStrategy: TracingStrategy +) : CompletedCallInfo + class PSIErrorCallInfo( override val callResolutionResult: CallResolutionResult, val result: OverloadResolutionResults diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt index 02405c8eeb9..9532fce34b2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt @@ -24,9 +24,11 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getCall import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall import org.jetbrains.kotlin.resolve.calls.components.InferenceSession +import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext import org.jetbrains.kotlin.resolve.calls.context.ContextDependency import org.jetbrains.kotlin.resolve.calls.inference.buildResultingSubstitutor +import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.results.* import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo @@ -61,7 +63,9 @@ class PSICallResolver( private val argumentTypeResolver: ArgumentTypeResolver, private val effectSystem: EffectSystem, private val constantExpressionEvaluator: ConstantExpressionEvaluator, - private val dataFlowValueFactory: DataFlowValueFactory + private val dataFlowValueFactory: DataFlowValueFactory, + private val postponedArgumentsAnalyzer: PostponedArgumentsAnalyzer, + private val kotlinConstraintSystemCompleter: KotlinConstraintSystemCompleter ) { private val givenCandidatesName = Name.special("") @@ -160,7 +164,8 @@ class PSICallResolver( KotlinResolutionCallbacksImpl( trace, expressionTypingServices, typeApproximator, argumentTypeResolver, languageVersionSettings, kotlinToResolvedCallTransformer, - dataFlowValueFactory, inferenceSession, constantExpressionEvaluator, typeResolver + dataFlowValueFactory, inferenceSession, constantExpressionEvaluator, typeResolver, + this, postponedArgumentsAnalyzer, kotlinConstraintSystemCompleter, callComponents ) private fun calculateExpectedType(context: BasicCallResolutionContext): UnwrappedType? { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSIKotlinCalls.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSIKotlinCalls.kt index 7ce0851d645..c80f965b284 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSIKotlinCalls.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSIKotlinCalls.kt @@ -16,9 +16,12 @@ package org.jetbrains.kotlin.resolve.calls.tower +import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.Call +import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.calls.CallTransformer +import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy @@ -26,6 +29,7 @@ import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategyForInvoke import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.util.OperatorNameConventions +import org.jetbrains.kotlin.utils.addToStdlib.safeAs val KotlinCall.psiKotlinCall: PSIKotlinCall get() { @@ -35,6 +39,9 @@ val KotlinCall.psiKotlinCall: PSIKotlinCall return this as PSIKotlinCall } +fun KotlinCall.getResolvedPsiKotlinCall(trace: BindingTrace): NewResolvedCallImpl? = + psiKotlinCall.psiCall.getResolvedCall(trace.bindingContext) as? NewResolvedCallImpl + abstract class PSIKotlinCall : KotlinCall { abstract val psiCall: Call abstract val startingDataFlowInfo: DataFlowInfo diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt index e5a20afffd2..962b76057d1 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt @@ -7,9 +7,12 @@ package org.jetbrains.kotlin.resolve.calls.components import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor +import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo +import org.jetbrains.kotlin.types.NonFixedType import org.jetbrains.kotlin.types.UnwrappedType // stateless component @@ -22,6 +25,7 @@ interface KotlinResolutionStatelessCallbacks { fun isSuperExpression(receiver: SimpleKotlinCallArgument?): Boolean fun getScopeTowerForCallableReferenceArgument(argument: CallableReferenceKotlinCallArgument): ImplicitScopeTower fun getVariableCandidateIfInvoke(functionCall: KotlinCall): KotlinResolutionCandidate? + fun isCoroutineCall(argument: KotlinCallArgument, parameter: ValueParameterDescriptor): Boolean } // This components hold state (trace). Work with this carefully. @@ -31,8 +35,9 @@ interface KotlinResolutionCallbacks { isSuspend: Boolean, receiverType: UnwrappedType?, parameters: List, - expectedReturnType: UnwrappedType? // null means, that return type is not proper i.e. it depends on some type variables - ): List + expectedReturnType: UnwrappedType?, // null means, that return type is not proper i.e. it depends on some type variables + stubsForPostponedVariables: Map + ): Pair, InferenceSession?> fun bindStubResolvedCallForCandidate(candidate: ResolvedCallAtom) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/InferenceSession.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/InferenceSession.kt index 83c11015942..f94428b0e27 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/InferenceSession.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/InferenceSession.kt @@ -6,9 +6,13 @@ package org.jetbrains.kotlin.resolve.calls.components 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.CallResolutionResult +import org.jetbrains.kotlin.resolve.calls.model.CompletedCallResolutionResult import org.jetbrains.kotlin.resolve.calls.model.KotlinResolutionCandidate import org.jetbrains.kotlin.resolve.calls.model.PartialCallResolutionResult +import org.jetbrains.kotlin.types.TypeConstructor +import org.jetbrains.kotlin.types.UnwrappedType interface InferenceSession { companion object { @@ -16,20 +20,28 @@ interface InferenceSession { override fun shouldRunCompletion(candidate: KotlinResolutionCandidate): Boolean = true override fun addPartialCallInfo(callInfo: PartialCallInfo) {} override fun addErrorCallInfo(callInfo: ErrorCallInfo) {} + override fun addCompletedCallInfo(callInfo: CompletedCallInfo) {} override fun currentConstraintSystem(): ConstraintStorage = ConstraintStorage.Empty + override fun inferPostponedVariables(initialStorage: ConstraintStorage): Map = emptyMap() } } fun shouldRunCompletion(candidate: KotlinResolutionCandidate): Boolean fun addPartialCallInfo(callInfo: PartialCallInfo) + fun addCompletedCallInfo(callInfo: CompletedCallInfo) fun addErrorCallInfo(callInfo: ErrorCallInfo) fun currentConstraintSystem(): ConstraintStorage + fun inferPostponedVariables(initialStorage: ConstraintStorage): Map } interface PartialCallInfo { val callResolutionResult: PartialCallResolutionResult } +interface CompletedCallInfo { + val callResolutionResult: CompletedCallResolutionResult +} + interface ErrorCallInfo { val callResolutionResult: CallResolutionResult } \ 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 82439b627bf..e7d3193efce 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 @@ -8,9 +8,10 @@ package org.jetbrains.kotlin.resolve.calls.components import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder 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.ConstraintStorage -import org.jetbrains.kotlin.resolve.calls.inference.model.LambdaArgumentConstraintPosition +import org.jetbrains.kotlin.resolve.calls.inference.model.* import org.jetbrains.kotlin.resolve.calls.model.* +import org.jetbrains.kotlin.types.NonFixedType +import org.jetbrains.kotlin.types.TypeConstructor import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.typeUtil.builtIns @@ -18,7 +19,8 @@ class PostponedArgumentsAnalyzer( private val callableReferenceResolver: CallableReferenceResolver ) { interface Context { - fun buildCurrentSubstitutor(): NewTypeSubstitutor + 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 @@ -42,7 +44,9 @@ class PostponedArgumentsAnalyzer( analyzeLambda(c, resolutionCallbacks, argument, diagnosticsHolder) is LambdaWithTypeVariableAsExpectedTypeAtom -> - analyzeLambda(c, resolutionCallbacks, argument.transformToResolvedLambda(c.getBuilder()), diagnosticsHolder) + analyzeLambda( + c, resolutionCallbacks, argument.transformToResolvedLambda(c.getBuilder()), diagnosticsHolder + ) is ResolvedCallableReferenceAtom -> callableReferenceResolver.processCallableReferenceArgument(c.getBuilder(), argument, diagnosticsHolder) @@ -59,7 +63,9 @@ class PostponedArgumentsAnalyzer( lambda: ResolvedLambdaAtom, diagnosticHolder: KotlinDiagnosticsHolder ) { - val currentSubstitutor = c.buildCurrentSubstitutor() + val stubsForPostponedVariables = c.bindingStubsForPostponedVariables() + val currentSubstitutor = c.buildCurrentSubstitutor(stubsForPostponedVariables.mapKeys { it.key.freshTypeConstructor }) + fun substitute(type: UnwrappedType) = currentSubstitutor.safeSubstitute(type) val receiver = lambda.receiver?.let(::substitute) @@ -75,12 +81,13 @@ class PostponedArgumentsAnalyzer( else -> null } - val returnArguments = resolutionCallbacks.analyzeAndGetLambdaReturnArguments( + val (returnArguments, inferenceSession) = resolutionCallbacks.analyzeAndGetLambdaReturnArguments( lambda.atom, lambda.isSuspend, receiver, parameters, - expectedTypeForReturnArguments + expectedTypeForReturnArguments, + stubsForPostponedVariables ) returnArguments.forEach { c.addSubsystemFromArgument(it) } @@ -94,6 +101,20 @@ class PostponedArgumentsAnalyzer( c.getBuilder().addSubtypeConstraint(lambda.returnType.let(::substitute), unitType, LambdaArgumentConstraintPosition(lambda)) } + if (inferenceSession != null) { + val storageSnapshot = c.getBuilder().copyCurrentStorage() + + val postponedVariables = inferenceSession.inferPostponedVariables(storageSnapshot) + + for ((constructor, resultType) in postponedVariables) { + val variableWithConstraints = storageSnapshot.notFixedTypeVariables[constructor] ?: continue + val variable = variableWithConstraints.typeVariable + + c.getBuilder().unmarkPostponedVariable(variable) + c.getBuilder().addEqualityConstraint(variable.defaultType, resultType, CoroutinePosition()) + } + } + lambda.setAnalyzedResults(returnArguments, subResolvedKtPrimitives) } } \ No newline at end of file diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt index d04296ebe73..b70a87eb5f2 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt @@ -9,10 +9,7 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.resolve.calls.components.TypeArgumentsToParametersMapper.TypeArgumentsMapping.NoExplicitArguments import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor -import org.jetbrains.kotlin.resolve.calls.inference.model.DeclaredUpperBoundConstraintPosition -import org.jetbrains.kotlin.resolve.calls.inference.model.ExplicitTypeParameterConstraintPosition -import org.jetbrains.kotlin.resolve.calls.inference.model.KnownTypeParameterConstraintPosition -import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableFromCallableDescriptor +import org.jetbrains.kotlin.resolve.calls.inference.model.* import org.jetbrains.kotlin.resolve.calls.inference.substitute import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.smartcasts.getReceiverValueWithSmartCast @@ -21,6 +18,7 @@ import org.jetbrains.kotlin.resolve.calls.tower.InfixCallNoInfixModifier import org.jetbrains.kotlin.resolve.calls.tower.InvokeConventionCallNoOperatorModifier import org.jetbrains.kotlin.resolve.calls.tower.VisibilityError import org.jetbrains.kotlin.types.ErrorUtils +import org.jetbrains.kotlin.types.typeUtil.contains import org.jetbrains.kotlin.utils.addToStdlib.safeAs internal object CheckInstantiationOfAbstractClass : ResolutionPart() { @@ -194,6 +192,20 @@ internal object CreateFreshVariablesSubstitutor : ResolutionPart() { } } +internal object InferLaterInitializerResolutionPart : ResolutionPart() { + override fun KotlinResolutionCandidate.process(workIndex: Int) { + resolvedCall.argumentToCandidateParameter + .filter { (argument, parameter) -> callComponents.statelessCallbacks.isCoroutineCall(argument, parameter) } + .flatMap { (_, parameter) -> + resolvedCall.substitutor.freshVariables.filter { variable -> + parameter.type.contains { it.constructor == variable.originalTypeParameter.typeConstructor } + } + } + .distinct() + .forEach { csBuilder.markPostponedVariable(it) } + } +} + internal object CheckExplicitReceiverKindConsistency : ResolutionPart() { private fun KotlinResolutionCandidate.hasError(): Nothing = error( 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 b61d966fb08..2be65019c00 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 @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintPosition +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 @@ -29,6 +30,8 @@ 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 addSubtypeConstraint(lowerType: UnwrappedType, upperType: UnwrappedType, position: ConstraintPosition) fun addEqualityConstraint(a: UnwrappedType, b: UnwrappedType, position: ConstraintPosition) @@ -45,6 +48,8 @@ interface ConstraintSystemBuilder : ConstraintSystemOperation { fun runTransaction(runOperations: ConstraintSystemOperation.() -> Boolean): Boolean fun buildCurrentSubstitutor(): NewTypeSubstitutor + + fun copyCurrentStorage(): ConstraintStorage } fun ConstraintSystemBuilder.addSubtypeConstraintIfCompatible( 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 878e50c9e5d..6957dd550a8 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,13 +20,12 @@ 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.NewConstraintSystemImpl +import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.types.* -fun ConstraintStorage.buildCurrentSubstitutor() = NewTypeSubstitutorByConstructorMap(fixedTypeVariables.entries.associate { - it.key to it.value -}) +fun ConstraintStorage.buildCurrentSubstitutor(additionalBindings: Map): NewTypeSubstitutorByConstructorMap = + NewTypeSubstitutorByConstructorMap(fixedTypeVariables.entries.associate { it.key to it.value } + additionalBindings) fun ConstraintStorage.buildResultingSubstitutor(): NewTypeSubstitutor { val currentSubstitutorMap = fixedTypeVariables.entries.associate { 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 2022afec3de..360e18df6ae 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 @@ -38,6 +38,7 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val var maxTypeDepthFromInitialConstraints: Int val notFixedTypeVariables: MutableMap + val fixedTypeVariables: MutableMap fun addInitialConstraint(initialConstraint: InitialConstraint) fun addError(error: KotlinCallDiagnostic) 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 0d61d793b37..a12cafec84f 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 @@ -27,9 +27,13 @@ class KotlinConstraintSystemCompleter( interface Context : VariableFixationFinder.Context, ResultTypeResolver.Context { override val notFixedTypeVariables: Map + override val postponedTypeVariables: List + // type can be proper if it not contains not fixed type variables fun canBeProper(type: UnwrappedType): Boolean + fun containsOnlyFixedOrPostponedVariables(type: UnwrappedType): Boolean + // mutable operations fun addError(error: KotlinCallDiagnostic) @@ -42,11 +46,28 @@ class KotlinConstraintSystemCompleter( topLevelAtoms: List, topLevelType: UnwrappedType, analyze: (PostponedResolvedAtom) -> Unit + ) { + runCompletion(c, completionMode, topLevelAtoms, topLevelType, collectVariablesFromContext = false, analyze = analyze) + } + + fun completeConstraintSystem(c: Context, topLevelType: UnwrappedType) { + runCompletion(c, ConstraintSystemCompletionMode.FULL, emptyList(), topLevelType, collectVariablesFromContext = true) { + error("Shouldn't be called in complete constraint system mode") + } + } + + private fun runCompletion( + c: Context, + completionMode: ConstraintSystemCompletionMode, + topLevelAtoms: List, + topLevelType: UnwrappedType, + collectVariablesFromContext: Boolean, + analyze: (PostponedResolvedAtom) -> Unit ) { while (true) { if (analyzePostponeArgumentIfPossible(c, topLevelAtoms, analyze)) continue - val allTypeVariables = getOrderedAllTypeVariables(c, topLevelAtoms) + val allTypeVariables = getOrderedAllTypeVariables(c, collectVariablesFromContext, topLevelAtoms) val postponedKtPrimitives = getOrderedNotAnalyzedPostponedArguments(topLevelAtoms) val variableForFixation = variableFixationFinder.findFirstVariableForFixation( c, allTypeVariables, postponedKtPrimitives, completionMode, topLevelType @@ -75,6 +96,10 @@ class KotlinConstraintSystemCompleter( if (completionMode == ConstraintSystemCompletionMode.FULL) { // force resolution for all not-analyzed argument's getOrderedNotAnalyzedPostponedArguments(topLevelAtoms).forEach(analyze) + + if (c.notFixedTypeVariables.isNotEmpty() && c.postponedTypeVariables.isEmpty()) { + runCompletion(c, completionMode, topLevelAtoms, topLevelType, analyze) + } } } @@ -130,7 +155,13 @@ class KotlinConstraintSystemCompleter( return notAnalyzedArguments } - private fun getOrderedAllTypeVariables(c: Context, topLevelAtoms: List): List { + private fun getOrderedAllTypeVariables( + c: Context, + collectVariablesFromContext: Boolean, + topLevelAtoms: List + ): List { + if (collectVariablesFromContext) return c.notFixedTypeVariables.keys.toList() + fun ResolvedAtom.process(to: LinkedHashSet) { val typeVariables = when (this) { is ResolvedCallAtom -> substitutor.freshVariables @@ -166,7 +197,7 @@ class KotlinConstraintSystemCompleter( private fun canWeAnalyzeIt(c: Context, argument: PostponedResolvedAtom): Boolean { if (argument.analyzed) return false - return argument.inputTypes.all { c.canBeProper(it) } + return argument.inputTypes.all { c.containsOnlyFixedOrPostponedVariables(it) } } private fun fixVariable( @@ -176,9 +207,15 @@ class KotlinConstraintSystemCompleter( postponedResolveKtPrimitives: List ) { val direction = TypeVariableDirectionCalculator(c, postponedResolveKtPrimitives, topLevelType).getDirection(variableWithConstraints) + fixVariable(c, variableWithConstraints, direction) + } + fun fixVariable( + c: Context, + variableWithConstraints: VariableWithConstraints, + direction: TypeVariableDirectionCalculator.ResolveDirection + ) { val resultType = resultTypeResolver.findResultType(c, variableWithConstraints, direction) - c.fixVariable(variableWithConstraints.typeVariable, resultType) } } \ No newline at end of file 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 c4e774ec262..65aad65cb04 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,6 +20,7 @@ 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 @@ -29,6 +30,7 @@ import org.jetbrains.kotlin.types.typeUtil.contains class VariableFixationFinder { interface Context { val notFixedTypeVariables: Map + val postponedTypeVariables: List } data class VariableForFixation(val variable: TypeConstructor, val hasProperConstraint: Boolean) @@ -67,10 +69,12 @@ class VariableFixationFinder { completionMode: ConstraintSystemCompletionMode, topLevelType: UnwrappedType ): VariableForFixation? { - val dependencyProvider = TypeVariableDependencyInformationProvider(notFixedTypeVariables, postponedKtPrimitives, - topLevelType.takeIf { completionMode == PARTIAL }) + val dependencyProvider = TypeVariableDependencyInformationProvider( + notFixedTypeVariables, postponedKtPrimitives, topLevelType.takeIf { completionMode == PARTIAL } + ) val candidate = allTypeVariables.maxBy { getTypeVariableReadiness(it, dependencyProvider) } ?: return null + val candidateReadiness = getTypeVariableReadiness(candidate, dependencyProvider) return when (candidateReadiness) { TypeVariableFixationReadiness.FORBIDDEN -> null 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 064ec070fb2..bcbdb71844d 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 @@ -69,6 +69,10 @@ class IncorporationConstraintPosition(val from: ConstraintPosition, val initialC override fun toString() = "Incorporate $initialConstraint from position $from" } +class CoroutinePosition() : ConstraintPosition() { + override fun toString(): String = "for coroutine call" +} + @Deprecated("Should be used only in SimpleConstraintSystemImpl") object SimpleConstraintSystemConstraintPosition : ConstraintPosition() 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 efd65ce805e..07f4a410e36 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,6 +5,7 @@ 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 @@ -42,6 +43,7 @@ interface ConstraintStorage { val errors: List val hasContradiction: Boolean val fixedTypeVariables: Map + val postponedTypeVariables: List object Empty : ConstraintStorage { override val allTypeVariables: Map get() = emptyMap() @@ -51,6 +53,7 @@ interface ConstraintStorage { override val errors: List get() = emptyList() override val hasContradiction: Boolean get() = false override val fixedTypeVariables: Map get() = emptyMap() + override val postponedTypeVariables: List get() = emptyList() } } 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 41342630e46..560f6603bd2 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 @@ -5,13 +5,14 @@ package org.jetbrains.kotlin.resolve.calls.inference.model +import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor import org.jetbrains.kotlin.resolve.calls.inference.trimToSize 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 java.util.* import kotlin.collections.ArrayList +import kotlin.collections.LinkedHashMap class MutableVariableWithConstraints( @@ -25,6 +26,7 @@ class MutableVariableWithConstraints( } return simplifiedConstraints!! } + private val mutableConstraints = ArrayList(constraints) private var simplifiedConstraints: List? = null @@ -94,4 +96,33 @@ internal class MutableConstraintStorage : ConstraintStorage { override val errors: MutableList = ArrayList() override val hasContradiction: Boolean get() = errors.any { !it.candidateApplicability.isSuccess } override val fixedTypeVariables: MutableMap = LinkedHashMap() -} \ No newline at end of file + override val postponedTypeVariables: ArrayList = ArrayList() + + fun copy(): ConstraintStorage { + return object : ConstraintStorage { + override val allTypeVariables: Map = + this@MutableConstraintStorage.allTypeVariables.toMap() + + override val notFixedTypeVariables: Map = + this@MutableConstraintStorage.notFixedTypeVariables.toMap() + + override val initialConstraints: List = + this@MutableConstraintStorage.initialConstraints.toList() + + override val maxTypeDepthFromInitialConstraints: Int = + this@MutableConstraintStorage.maxTypeDepthFromInitialConstraints + + override val errors: List = + this@MutableConstraintStorage.errors.toList() + + override val hasContradiction: Boolean = + this@MutableConstraintStorage.hasContradiction + + override val fixedTypeVariables: Map = + this@MutableConstraintStorage.fixedTypeVariables.toMap() + + override val postponedTypeVariables: List = + this@MutableConstraintStorage.postponedTypeVariables.toList() + } + } +} 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 352be20896e..dbf27d6ad46 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 @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintS import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor import org.jetbrains.kotlin.resolve.calls.inference.components.ResultTypeResolver import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic +import org.jetbrains.kotlin.types.NonFixedType import org.jetbrains.kotlin.types.TypeConstructor import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.typeUtil.contains @@ -70,6 +71,14 @@ class NewConstraintSystemImpl( storage.notFixedTypeVariables[variable.freshTypeConstructor] = MutableVariableWithConstraints(variable) } + override fun markPostponedVariable(variable: NewTypeVariable) { + storage.postponedTypeVariables += variable + } + + override fun unmarkPostponedVariable(variable: NewTypeVariable) { + storage.postponedTypeVariables -= variable + } + override fun addSubtypeConstraint(lowerType: UnwrappedType, upperType: UnwrappedType, position: ConstraintPosition) = constraintInjector.addInitialSubtypeConstraint( apply { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) }, @@ -163,6 +172,7 @@ class NewConstraintSystemImpl( Math.max(storage.maxTypeDepthFromInitialConstraints, otherSystem.maxTypeDepthFromInitialConstraints) storage.errors.addAll(otherSystem.errors) storage.fixedTypeVariables.putAll(otherSystem.fixedTypeVariables) + storage.postponedTypeVariables.addAll(otherSystem.postponedTypeVariables) } // ResultTypeResolver.Context, ConstraintSystemBuilder @@ -204,6 +214,18 @@ class NewConstraintSystemImpl( return storage.notFixedTypeVariables } + override val fixedTypeVariables: MutableMap + get() { + checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) + return storage.fixedTypeVariables + } + + override val postponedTypeVariables: List + get() { + checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) + return storage.postponedTypeVariables + } + // ConstraintInjector.Context, KotlinConstraintSystemCompleter.Context override fun addError(error: KotlinCallDiagnostic) { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) @@ -232,10 +254,33 @@ class NewConstraintSystemImpl( return !type.contains { storage.notFixedTypeVariables.containsKey(it.constructor) } } + override fun containsOnlyFixedOrPostponedVariables(type: UnwrappedType): 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) + } + } + // PostponedArgumentsAnalyzer.Context override fun buildCurrentSubstitutor(): NewTypeSubstitutor { checkState(State.BUILDING, State.COMPLETION) - return storage.buildCurrentSubstitutor() + return buildCurrentSubstitutor(emptyMap()) + } + + override fun buildCurrentSubstitutor(additionalBindings: Map): NewTypeSubstitutor { + checkState(State.BUILDING, State.COMPLETION) + return storage.buildCurrentSubstitutor(additionalBindings) + } + + override fun bindingStubsForPostponedVariables(): Map { + checkState(State.BUILDING, State.COMPLETION) + return storage.postponedTypeVariables.associate { it to NonFixedType(it.freshTypeConstructor) } + } + + override fun copyCurrentStorage(): ConstraintStorage { + checkState(State.BUILDING, State.COMPLETION) + return storage.copy() } // PostponedArgumentsAnalyzer.Context diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinResolverContext.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinResolverContext.kt index 07eb8099c83..ba6f245c2d2 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinResolverContext.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinResolverContext.kt @@ -191,7 +191,8 @@ enum class KotlinCallKind(vararg resolutionPart: ResolutionPart) { NoArguments, CreateFreshVariablesSubstitutor, CheckExplicitReceiverKindConsistency, - CheckReceivers + CheckReceivers, + InferLaterInitializerResolutionPart ), FUNCTION( CheckInstantiationOfAbstractClass, @@ -205,7 +206,8 @@ enum class KotlinCallKind(vararg resolutionPart: ResolutionPart) { CheckExplicitReceiverKindConsistency, CheckReceivers, CheckArguments, - CheckExternalArgument + CheckExternalArgument, + InferLaterInitializerResolutionPart ), INVOKE(*FUNCTION.resolutionSequence.toTypedArray()), UNSUPPORTED(); 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 54e52ac24e7..a779c728f90 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 @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl +import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableFromCallableDescriptor import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tower.* import org.jetbrains.kotlin.types.TypeSubstitutor diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/applyInsideCoroutine.kt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/applyInsideCoroutine.kt new file mode 100644 index 00000000000..d36f1518446 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/applyInsideCoroutine.kt @@ -0,0 +1,35 @@ +// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_ANONYMOUS_PARAMETER -UNUSED_VARIABLE +// !WITH_NEW_INFERENCE + +class Controller { + suspend fun yield(t: T) {} +} + +fun generate(g: suspend Controller.() -> Unit): S = TODO() + +val test1 = generate { + apply { + yield(4) + } +} + +val test2 = generate { + yield(B) + apply { + yield(C) + } +} + +val test3 = generate { + this.let { + yield(B) + } + + apply { + yield(C) + } +} + +interface A +object B : A +object C : A \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/applyInsideCoroutine.txt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/applyInsideCoroutine.txt new file mode 100644 index 00000000000..f1e995ea666 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/applyInsideCoroutine.txt @@ -0,0 +1,34 @@ +package + +public val test1: kotlin.Int +public val test2: A +public val test3: A +public fun generate(/*0*/ g: suspend Controller.() -> kotlin.Unit): S + +public interface A { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public object B : A { + private constructor B() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public object C : A { + private constructor C() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class Controller { + public constructor Controller() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + public final suspend fun yield(/*0*/ t: T): kotlin.Unit +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/extensionSuspend.kt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/extensionSuspend.kt index 542c3864c7f..f23e66ed278 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/extensionSuspend.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/extensionSuspend.kt @@ -4,7 +4,7 @@ class GenericController { suspend fun yield(t: T) {} } -suspend fun GenericController.yieldAll(s: Collection) {} +suspend fun GenericController.yieldAll(s: Collection) {} fun generate(g: suspend GenericController.() -> Unit): S = TODO() diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/extensionSuspend.txt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/extensionSuspend.txt index 93bdcaf9b80..b1212a4de77 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/extensionSuspend.txt +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/extensionSuspend.txt @@ -6,7 +6,7 @@ public val test3: A public val test4: A public fun generate(/*0*/ g: suspend GenericController.() -> kotlin.Unit): S public fun setOf(/*0*/ vararg x: X /*kotlin.Array*/): kotlin.collections.Set -public suspend fun GenericController.yieldAll(/*0*/ s: kotlin.collections.Collection): kotlin.Unit +public suspend fun GenericController.yieldAll(/*0*/ s: kotlin.collections.Collection): kotlin.Unit public interface A { public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/suspendCallsWithErrors.kt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/suspendCallsWithErrors.kt new file mode 100644 index 00000000000..cbea4621824 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/suspendCallsWithErrors.kt @@ -0,0 +1,18 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// !WITH_NEW_INFERENCE + +class Controller { + suspend fun yield(t: T) {} +} + +fun generate(g: suspend Controller.() -> Unit): S = TODO() + +class A + +val test1 = generate { + yield(A) +} + +val test2: Int = generate { + yield(A()) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/suspendCallsWithErrors.txt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/suspendCallsWithErrors.txt new file mode 100644 index 00000000000..39d9fb735ab --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/suspendCallsWithErrors.txt @@ -0,0 +1,20 @@ +package + +public val test1: [ERROR : Error type for ParseError-argument VALUE_ARGUMENT] +public val test2: kotlin.Int +public fun generate(/*0*/ g: suspend Controller.() -> kotlin.Unit): S + +public final class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class Controller { + public constructor Controller() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + public final suspend fun yield(/*0*/ t: T): kotlin.Unit +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/suspendCallsWrongUpperBound.kt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/suspendCallsWrongUpperBound.kt new file mode 100644 index 00000000000..42c5e4476ba --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/suspendCallsWrongUpperBound.kt @@ -0,0 +1,12 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// !WITH_NEW_INFERENCE + +class Controller { + suspend fun yield(t: T) {} +} + +fun generate(g: suspend Controller.() -> Unit): S = TODO() + +val test = generate { + yield("foo") +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/suspendCallsWrongUpperBound.txt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/suspendCallsWrongUpperBound.txt new file mode 100644 index 00000000000..08125502bb3 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/suspendCallsWrongUpperBound.txt @@ -0,0 +1,12 @@ +package + +public val test: kotlin.String +public fun generate(/*0*/ g: suspend Controller.() -> kotlin.Unit): S + +public final class Controller { + public constructor Controller() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + public final suspend fun yield(/*0*/ t: T): kotlin.Unit +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java index 1f0faf1d5b0..e3569b7a1fc 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java @@ -1533,6 +1533,11 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); } + @TestMetadata("applyInsideCoroutine.kt") + public void testApplyInsideCoroutine() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/applyInsideCoroutine.kt"); + } + @TestMetadata("correctMember.kt") public void testCorrectMember() throws Exception { runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/correctMember.kt"); @@ -1583,6 +1588,16 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/simpleGenerator.kt"); } + @TestMetadata("suspendCallsWithErrors.kt") + public void testSuspendCallsWithErrors() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/suspendCallsWithErrors.kt"); + } + + @TestMetadata("suspendCallsWrongUpperBound.kt") + public void testSuspendCallsWrongUpperBound() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/suspendCallsWrongUpperBound.kt"); + } + @TestMetadata("typeFromReceiver.kt") public void testTypeFromReceiver() throws Exception { runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/typeFromReceiver.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java index c223c88021e..42ce493f8e3 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java @@ -1533,6 +1533,11 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); } + @TestMetadata("applyInsideCoroutine.kt") + public void testApplyInsideCoroutine() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/applyInsideCoroutine.kt"); + } + @TestMetadata("correctMember.kt") public void testCorrectMember() throws Exception { runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/correctMember.kt"); @@ -1583,6 +1588,16 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/simpleGenerator.kt"); } + @TestMetadata("suspendCallsWithErrors.kt") + public void testSuspendCallsWithErrors() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/suspendCallsWithErrors.kt"); + } + + @TestMetadata("suspendCallsWrongUpperBound.kt") + public void testSuspendCallsWrongUpperBound() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/suspendCallsWrongUpperBound.kt"); + } + @TestMetadata("typeFromReceiver.kt") public void testTypeFromReceiver() throws Exception { runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/typeFromReceiver.kt"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/NonFixedType.kt b/core/descriptors/src/org/jetbrains/kotlin/types/NonFixedType.kt new file mode 100644 index 00000000000..d58e2421996 --- /dev/null +++ b/core/descriptors/src/org/jetbrains/kotlin/types/NonFixedType.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2018 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 + +import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.resolve.scopes.MemberScope + +class NonFixedType(val originalTypeVariable: TypeConstructor) : SimpleType() { + override val constructor: TypeConstructor = + ErrorUtils.createErrorTypeConstructor("Constructor for non fixed type: $originalTypeVariable") + + override val arguments: List + get() = emptyList() + + override val isMarkedNullable: Boolean + get() = false + + override val memberScope: MemberScope = + ErrorUtils.createErrorScope("Scope for non fixed type: $originalTypeVariable") + + override val annotations: Annotations + get() = Annotations.EMPTY + + override fun replaceAnnotations(newAnnotations: Annotations): SimpleType = this + + override fun makeNullableAsSpecified(newNullability: Boolean): SimpleType = this + + override fun toString(): String { + return "NonFixed: $originalTypeVariable" + } +} \ No newline at end of file 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 0ca16a093bb..b02f101b8c3 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewKotlinTypeChecker.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewKotlinTypeChecker.kt @@ -186,6 +186,8 @@ object NewKotlinTypeChecker : KotlinTypeChecker { return StrictEqualityTypeChecker.strictEqualTypes(subType.makeNullableAsSpecified(false), superType.makeNullableAsSpecified(false)) } + if (subType is NonFixedType || superType is NonFixedType) return true + if (superType is NewCapturedType && superType.lowerType != null) { when (getLowerCapturedTypePolicy(subType, superType)) { CHECK_ONLY_LOWER -> return isSubtypeOf(subType, superType.lowerType)