From 514ac7dc8f05657f18e25ef643659ea30bfca841 Mon Sep 17 00:00:00 2001 From: Victor Petukhov Date: Thu, 9 Jul 2020 15:17:07 +0300 Subject: [PATCH] NI: introduce simple calls storage (which aren't gone through type inference) in coroutine inference session to further substitute postponed variable ^KT-40151 Fixed --- .../ir/FirBlackBoxCodegenTestGenerated.java | 5 + .../inference/CoroutineInferenceSession.kt | 91 ++++++++++++------- .../DoubleColonExpressionResolver.kt | 11 ++- .../substituteStubTypeIntoCR.kt | 24 +++++ .../codegen/BlackBoxCodegenTestGenerated.java | 5 + .../LightAnalysisModeTestGenerated.java | 5 + .../ir/IrBlackBoxCodegenTestGenerated.java | 5 + .../IrJsCodegenBoxES6TestGenerated.java | 5 + .../IrJsCodegenBoxTestGenerated.java | 5 + .../semantics/JsCodegenBoxTestGenerated.java | 5 + 10 files changed, 124 insertions(+), 37 deletions(-) create mode 100644 compiler/testData/codegen/box/builderInference/substituteStubTypeIntoCR.kt diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index fc23a157949..62dcce0493a 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -1708,6 +1708,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/builderInference/lackOfNullCheckOnNullableInsideBuild.kt"); } + @TestMetadata("substituteStubTypeIntoCR.kt") + public void testSubstituteStubTypeIntoCR() throws Exception { + runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntoCR.kt"); + } + @TestMetadata("substituteStubTypeIntolambdaParameterDescriptor.kt") public void testSubstituteStubTypeIntolambdaParameterDescriptor() throws Exception { runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntolambdaParameterDescriptor.kt"); 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 3650a4346bf..1b121a2009b 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 @@ -5,22 +5,15 @@ package org.jetbrains.kotlin.resolve.calls.inference -import com.intellij.psi.PsiElement import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor -import org.jetbrains.kotlin.psi.KtDotQualifiedExpression -import org.jetbrains.kotlin.psi.KtDoubleColonExpression -import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.psi.KtReferenceExpression +import org.jetbrains.kotlin.descriptors.impl.* +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType import org.jetbrains.kotlin.psi.psiUtil.getParentOfType import org.jetbrains.kotlin.psi.psiUtil.isAncestor -import org.jetbrains.kotlin.resolve.BindingTrace -import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.MissingSupertypesResolver -import org.jetbrains.kotlin.resolve.TemporaryBindingTrace +import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver import org.jetbrains.kotlin.resolve.calls.components.CompletedCallInfo import org.jetbrains.kotlin.resolve.calls.components.NewConstraintSystemImpl @@ -34,10 +27,7 @@ import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.tower.* import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver -import org.jetbrains.kotlin.types.StubType -import org.jetbrains.kotlin.types.TypeApproximator -import org.jetbrains.kotlin.types.TypeConstructor -import org.jetbrains.kotlin.types.UnwrappedType +import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.expressions.DoubleColonExpressionResolver import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices import org.jetbrains.kotlin.types.typeUtil.contains @@ -64,6 +54,10 @@ class CoroutineInferenceSession( psiCallResolver, postponedArgumentsAnalyzer, kotlinConstraintSystemCompleter, callComponents, builtIns ) { private val commonCalls = arrayListOf() + + // Simple calls are calls which might not have gone through type inference, but may contain unsubstituted postponed variables inside their types. + private val simpleCommonCalls = arrayListOf() + private val diagnostics = arrayListOf() private var hasInapplicableCall = false @@ -85,6 +79,10 @@ class CoroutineInferenceSession( } || candidate.getSubResolvedAtoms().any { it.hasPostponed() } } + fun addSimpleCall(callExpression: KtExpression) { + simpleCommonCalls.add(callExpression) + } + override fun addCompletedCallInfo(callInfo: CompletedCallInfo) { require(callInfo is PSICompletedCallInfo) { "Wrong instance of callInfo: $callInfo" } @@ -260,38 +258,43 @@ class CoroutineInferenceSession( return commonSystem to effectivelyEmptyCommonSystem } + private fun reportDiagnostics(completedCall: CallInfo, resolvedCall: ResolvedCall<*>, diagnostics: List) { + kotlinToResolvedCallTransformer.reportCallDiagnostic( + completedCall.context, + trace, + completedCall.callResolutionResult.resultCallAtom, + resolvedCall.resultingDescriptor, + diagnostics + ) + } + private fun updateCalls(lambda: ResolvedLambdaAtom, commonSystem: NewConstraintSystemImpl) { val nonFixedToVariablesSubstitutor = createNonFixedTypeToVariableSubstitutor() val commonSystemSubstitutor = commonSystem.buildCurrentSubstitutor() as NewTypeSubstitutor val nonFixedTypesToResult = nonFixedToVariablesSubstitutor.map.mapValues { commonSystemSubstitutor.safeSubstitute(it.value) } - val nonFixedTypesToResultSubstitutor = ComposedSubstitutor(commonSystemSubstitutor, nonFixedToVariablesSubstitutor) + val atomCompleter = createResolvedAtomCompleter(nonFixedTypesToResultSubstitutor, topLevelCallContext) + for (completedCall in commonCalls) { updateCall(completedCall, nonFixedTypesToResultSubstitutor, nonFixedTypesToResult) - - kotlinToResolvedCallTransformer.reportCallDiagnostic( - completedCall.context, - trace, - completedCall.callResolutionResult.resultCallAtom, - completedCall.resolvedCall.resultingDescriptor, - commonSystem.diagnostics - ) + reportDiagnostics(completedCall, completedCall.resolvedCall, commonSystem.diagnostics) } - val lambdaAtomCompleter = createResolvedAtomCompleter(nonFixedTypesToResultSubstitutor, topLevelCallContext) for (callInfo in partiallyResolvedCallsInfo) { - val resolvedCall = completeCall(callInfo, lambdaAtomCompleter) ?: continue - kotlinToResolvedCallTransformer.reportCallDiagnostic( - callInfo.context, - trace, - callInfo.callResolutionResult.resultCallAtom, - resolvedCall.resultingDescriptor, - commonSystem.diagnostics - ) + val resolvedCall = completeCall(callInfo, atomCompleter) ?: continue + reportDiagnostics(callInfo, resolvedCall, commonSystem.diagnostics) } - lambdaAtomCompleter.completeAll(lambda) + + for (simpleCall in simpleCommonCalls) { + when (simpleCall) { + is KtCallableReferenceExpression -> updateCallableReferenceType(simpleCall, nonFixedTypesToResultSubstitutor) + else -> throw Exception("Unsupported call expression type") + } + } + + atomCompleter.completeAll(lambda) } private fun updateCall( @@ -313,6 +316,28 @@ class CoroutineInferenceSession( completeCall(completedCall, atomCompleter) } + private fun updateCallableReferenceType(expression: KtCallableReferenceExpression, substitutor: NewTypeSubstitutor) { + val functionDescriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, expression) as? SimpleFunctionDescriptorImpl ?: return + val returnType = functionDescriptor.returnType + + fun KotlinType.substituteAndApproximate() = typeApproximator.approximateDeclarationType( + substitutor.safeSubstitute(this.unwrap()), + local = true, + languageVersionSettings = topLevelCallContext.languageVersionSettings + ) + + if (returnType != null && returnType.contains { it is StubType }) { + functionDescriptor.setReturnType(returnType.substituteAndApproximate()) + } + + for (valueParameter in functionDescriptor.valueParameters) { + if (valueParameter !is ValueParameterDescriptorImpl || valueParameter.type !is StubType) + continue + + valueParameter.setOutType(valueParameter.type.substituteAndApproximate()) + } + } + private fun completeCall( callInfo: CallInfo, atomCompleter: ResolvedAtomCompleter diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt index 166917e6ee2..5f5f61e5dc7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.checkers.isBuiltInCoroutineContext import org.jetbrains.kotlin.resolve.calls.context.* +import org.jetbrains.kotlin.resolve.calls.inference.CoroutineInferenceSession import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsUtil import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo @@ -49,10 +50,7 @@ import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner import org.jetbrains.kotlin.types.expressions.FunctionWithBigAritySupport.LanguageVersionDependent import org.jetbrains.kotlin.types.expressions.typeInfoFactory.createTypeInfo import org.jetbrains.kotlin.types.refinement.TypeRefinement -import org.jetbrains.kotlin.types.typeUtil.builtIns -import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf -import org.jetbrains.kotlin.types.typeUtil.makeNotNullable -import org.jetbrains.kotlin.types.typeUtil.makeNullable +import org.jetbrains.kotlin.types.typeUtil.* import org.jetbrains.kotlin.utils.yieldIfNotNull import java.util.* import javax.inject.Inject @@ -558,6 +556,11 @@ class DoubleColonExpressionResolver( val (lhs, resolutionResults) = resolveCallableReference(expression, c, ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS) val result = getCallableReferenceType(expression, lhs, resolutionResults, c) val dataFlowInfo = (lhs as? DoubleColonLHS.Expression)?.dataFlowInfo ?: c.dataFlowInfo + + if (c.inferenceSession is CoroutineInferenceSession && result?.contains { it is StubType } == true) { + c.inferenceSession.addSimpleCall(expression) + } + return dataFlowAnalyzer.checkType(createTypeInfo(result, dataFlowInfo), expression, c) } diff --git a/compiler/testData/codegen/box/builderInference/substituteStubTypeIntoCR.kt b/compiler/testData/codegen/box/builderInference/substituteStubTypeIntoCR.kt new file mode 100644 index 00000000000..b013ed1bc05 --- /dev/null +++ b/compiler/testData/codegen/box/builderInference/substituteStubTypeIntoCR.kt @@ -0,0 +1,24 @@ +// IGNORE_BACKEND_FIR: JVM_IR +// IGNORE_BACKEND: JVM_IR +// KJS_WITH_FULL_RUNTIME +// WITH_RUNTIME +// WITH_COROUTINES + +import helpers.* +import kotlin.coroutines.* + +suspend fun foo() { + val x = sequence { + yield(1) + ::`yield` + } +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +fun box(): String { + builder { foo() } + return "OK" +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index a7cba8b9b13..340a6f62da0 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -1728,6 +1728,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/builderInference/lackOfNullCheckOnNullableInsideBuild.kt"); } + @TestMetadata("substituteStubTypeIntoCR.kt") + public void testSubstituteStubTypeIntoCR() throws Exception { + runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntoCR.kt"); + } + @TestMetadata("substituteStubTypeIntolambdaParameterDescriptor.kt") public void testSubstituteStubTypeIntolambdaParameterDescriptor() throws Exception { runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntolambdaParameterDescriptor.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index d373276e05b..249a6f433bf 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -1728,6 +1728,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/builderInference/lackOfNullCheckOnNullableInsideBuild.kt"); } + @TestMetadata("substituteStubTypeIntoCR.kt") + public void testSubstituteStubTypeIntoCR() throws Exception { + runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntoCR.kt"); + } + @TestMetadata("substituteStubTypeIntolambdaParameterDescriptor.kt") public void testSubstituteStubTypeIntolambdaParameterDescriptor() throws Exception { runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntolambdaParameterDescriptor.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 43cc85e8fa5..2e7bdfd5a01 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -1708,6 +1708,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/builderInference/lackOfNullCheckOnNullableInsideBuild.kt"); } + @TestMetadata("substituteStubTypeIntoCR.kt") + public void testSubstituteStubTypeIntoCR() throws Exception { + runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntoCR.kt"); + } + @TestMetadata("substituteStubTypeIntolambdaParameterDescriptor.kt") public void testSubstituteStubTypeIntolambdaParameterDescriptor() throws Exception { runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntolambdaParameterDescriptor.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index f3fd2ff4edc..0773a5111d9 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -1323,6 +1323,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/builderInference/lackOfNullCheckOnNullableInsideBuild.kt"); } + @TestMetadata("substituteStubTypeIntoCR.kt") + public void testSubstituteStubTypeIntoCR() throws Exception { + runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntoCR.kt"); + } + @TestMetadata("substituteStubTypeIntolambdaParameterDescriptor.kt") public void testSubstituteStubTypeIntolambdaParameterDescriptor() throws Exception { runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntolambdaParameterDescriptor.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index d8417ea1750..61f8cf6ab45 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -1333,6 +1333,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/builderInference/lackOfNullCheckOnNullableInsideBuild.kt"); } + @TestMetadata("substituteStubTypeIntoCR.kt") + public void testSubstituteStubTypeIntoCR() throws Exception { + runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntoCR.kt"); + } + @TestMetadata("substituteStubTypeIntolambdaParameterDescriptor.kt") public void testSubstituteStubTypeIntolambdaParameterDescriptor() throws Exception { runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntolambdaParameterDescriptor.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 2088c5d49d1..27e14b4b9b9 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -1333,6 +1333,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/builderInference/lackOfNullCheckOnNullableInsideBuild.kt"); } + @TestMetadata("substituteStubTypeIntoCR.kt") + public void testSubstituteStubTypeIntoCR() throws Exception { + runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntoCR.kt"); + } + @TestMetadata("substituteStubTypeIntolambdaParameterDescriptor.kt") public void testSubstituteStubTypeIntolambdaParameterDescriptor() throws Exception { runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntolambdaParameterDescriptor.kt");