NI: introduce simple calls storage (which aren't gone through type inference) in coroutine inference session to further substitute postponed variable
^KT-40151 Fixed
This commit is contained in:
Generated
+5
@@ -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");
|
||||
|
||||
+58
-33
@@ -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<PSICompletedCallInfo>()
|
||||
|
||||
// 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<KtExpression>()
|
||||
|
||||
private val diagnostics = arrayListOf<KotlinCallDiagnostic>()
|
||||
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<KotlinCallDiagnostic>) {
|
||||
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
|
||||
|
||||
+7
-4
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
+5
@@ -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");
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
Generated
+5
@@ -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");
|
||||
|
||||
Generated
+5
@@ -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");
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user