[FE 1.0] Take care standalone lambdas during updating types in the builder inference

^KT-50520 Fixed
This commit is contained in:
Victor Petukhov
2022-02-17 12:22:21 +01:00
committed by teamcity
parent c25e07119c
commit b411eb36e8
14 changed files with 115 additions and 60 deletions
@@ -19558,6 +19558,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/inference/builderInference/kt49887.kt");
}
@Test
@TestMetadata("kt50520.kt")
public void testKt50520() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/kt50520.kt");
}
@Test
@TestMetadata("kt51988.kt")
public void testKt51988() throws Exception {
@@ -190,9 +190,6 @@ class LocalVariableResolver(
initializeWithDefaultGetterSetter(propertyDescriptor)
trace.record(BindingContext.VARIABLE, variable, propertyDescriptor)
result = propertyDescriptor
if (inferenceSession is BuilderInferenceSession) {
inferenceSession.addLocalVariable(variable)
}
} else {
val variableDescriptor = resolveLocalVariableDescriptorWithType(scope, variable, null, trace)
// For a local variable the type must not be deferred
@@ -200,11 +197,11 @@ class LocalVariableResolver(
variableDescriptor, scope, variable, dataFlowInfo, inferenceSession, trace, local = true
)
variableDescriptor.setOutType(type)
if (inferenceSession is BuilderInferenceSession) {
inferenceSession.addLocalVariable(variable)
}
result = variableDescriptor
}
if (inferenceSession is BuilderInferenceSession) {
inferenceSession.addExpression(variable)
}
variableTypeAndInitializerResolver
.setConstantForVariableIfNeeded(result, scope, variable, dataFlowInfo, type, inferenceSession, trace)
// Type annotations also should be resolved
@@ -8,15 +8,15 @@ package org.jetbrains.kotlin.resolve.calls.inference
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.*
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
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.*
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
import org.jetbrains.kotlin.resolve.calls.util.shouldBeSubstituteWithStubTypes
import org.jetbrains.kotlin.resolve.calls.util.toOldSubstitution
import org.jetbrains.kotlin.resolve.calls.components.*
import org.jetbrains.kotlin.resolve.calls.components.candidate.ResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
@@ -25,6 +25,8 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.*
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.calls.util.shouldBeSubstituteWithStubTypes
import org.jetbrains.kotlin.resolve.calls.util.toOldSubstitution
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.resolve.descriptorUtil.hasBuilderInferenceAnnotation
import org.jetbrains.kotlin.resolve.descriptorUtil.shouldBeSubstituteWithStubTypes
@@ -73,11 +75,7 @@ class BuilderInferenceSession(
}
private val commonCalls = arrayListOf<PSICompletedCallInfo>()
private val localVariables = arrayListOf<KtVariableDeclaration>()
// These calls come from the old type inference
private val oldDoubleColonExpressionCalls = arrayListOf<KtExpression>()
private val commonExpressions = arrayListOf<KtExpression>()
private var hasInapplicableCall = false
@@ -130,10 +128,6 @@ class BuilderInferenceSession(
}
}
fun addOldCallableReferenceCalls(callExpression: KtExpression) {
oldDoubleColonExpressionCalls.add(callExpression)
}
override fun addCompletedCallInfo(callInfo: CompletedCallInfo) {
require(callInfo is PSICompletedCallInfo) { "Wrong instance of callInfo: $callInfo" }
@@ -158,8 +152,8 @@ class BuilderInferenceSession(
}
}
fun addLocalVariable(variable: KtVariableDeclaration) {
localVariables.add(variable)
fun addExpression(expression: KtExpression) {
commonExpressions.add(expression)
}
private fun anyReceiverContainStubType(descriptor: CallableDescriptor): Boolean {
@@ -180,7 +174,6 @@ class BuilderInferenceSession(
return null
}
@OptIn(ExperimentalStdlibApi::class)
private fun findAllParentBuildInferenceSessions() = buildList {
var currentSession: BuilderInferenceSession? = findParentBuildInferenceSession()
@@ -259,7 +252,7 @@ class BuilderInferenceSession(
kotlinConstraintSystemCompleter.completeConstraintSystem(
commonSystem.asConstraintSystemCompleterContext(),
builtIns.unitType,
partiallyResolvedCallsInfo.map { it.callResolutionResult.resultCallAtom },
commonPartiallyResolvedCalls.map { it.callResolutionResult.resultCallAtom },
completionMode,
diagnosticsHolder
)
@@ -277,7 +270,6 @@ class BuilderInferenceSession(
return commonSystem.fixedTypeVariables.cast() // TODO: SUB
}
@OptIn(ExperimentalStdlibApi::class)
private fun getNestedBuilderInferenceSessions() = buildList {
for (nestedSession in nestedInferenceSessions) {
when (nestedSession) {
@@ -448,13 +440,9 @@ class BuilderInferenceSession(
integrateConstraints(initialStorage, nonFixedToVariablesSubstitutor, false)
for (call in commonCalls) {
for (call in commonCalls + commonPartiallyResolvedCalls) {
val storage = call.callResolutionResult.constraintSystem.getBuilder().currentStorage()
integrateConstraints(storage, nonFixedToVariablesSubstitutor, false)
}
for (call in partiallyResolvedCallsInfo) {
val storage = call.callResolutionResult.constraintSystem.getBuilder().currentStorage()
integrateConstraints(storage, nonFixedToVariablesSubstitutor, true)
integrateConstraints(storage, nonFixedToVariablesSubstitutor, shouldIntegrateAllConstraints = call is PSIPartialCallInfo)
}
return commonSystem.notFixedTypeVariables.all { it.value.constraints.isEmpty() }
@@ -470,10 +458,31 @@ class BuilderInferenceSession(
)
}
private fun updateLocalVariable(localVariable: KtVariableDeclaration, substitutor: NewTypeSubstitutor) {
val descriptor = trace[BindingContext.VARIABLE, localVariable] as? LocalVariableDescriptor
if (descriptor != null && descriptor.type.shouldBeUpdated()) {
descriptor.setOutType(substitutor.safeSubstitute(descriptor.type.unwrap()))
private fun updateExpressionDescriptorAndType(expression: KtExpression, substitutor: NewTypeSubstitutor) {
val currentExpressionType = trace.getType(expression)
if (currentExpressionType != null) {
trace.recordType(expression, substitutor.safeSubstitute(currentExpressionType.unwrap()))
}
val (currentDescriptorType, updateDescriptorType) = when (expression) {
is KtLambdaExpression -> {
val descriptor = trace[BindingContext.FUNCTION, expression.functionLiteral] as? AnonymousFunctionDescriptor ?: return
val currentType = descriptor.returnType ?: return
currentType to descriptor::setReturnType
}
is KtVariableDeclaration -> {
val descriptor = trace[BindingContext.VARIABLE, expression] as? LocalVariableDescriptor ?: return
descriptor.type to descriptor::setOutType
}
is KtDoubleColonExpression -> {
completeDoubleColonExpression(expression, substitutor)
return
}
else -> return
}
if (currentDescriptorType.shouldBeUpdated()) {
updateDescriptorType(substitutor.safeSubstitute(currentDescriptorType.unwrap()))
}
}
@@ -513,12 +522,6 @@ class BuilderInferenceSession(
atomCompleter.substituteFunctionLiteralDescriptor(resolvedAtom = null, descriptor = declarationDescriptor, substitutor)
}
val recordedType = trace.getType(expression)
if (recordedType != null) {
trace.recordType(expression, substitutor.safeSubstitute(recordedType.unwrap()))
}
val targetExpression = when (expression) {
is KtCallableReferenceExpression -> expression.callableReference
is KtClassLiteralExpression -> expression.receiverExpression
@@ -610,25 +613,18 @@ class BuilderInferenceSession(
topLevelCallContext.replaceBindingTrace(findTopLevelTrace()).replaceInferenceSession(this)
)
for (localVariable in localVariables) {
updateLocalVariable(localVariable, nonFixedTypesToResultSubstitutor)
for (expression in commonExpressions) {
updateExpressionDescriptorAndType(expression, nonFixedTypesToResultSubstitutor)
}
for (completedCall in commonCalls) {
updateCall(completedCall, nonFixedTypesToResultSubstitutor, nonFixedTypesToResult)
reportErrors(completedCall, completedCall.resolvedCall, errors)
for (call in commonCalls) {
updateCall(call, nonFixedTypesToResultSubstitutor, nonFixedTypesToResult)
reportErrors(call, call.resolvedCall, errors)
}
for (callInfo in partiallyResolvedCallsInfo) {
val resolvedCall = completeCall(callInfo, atomCompleter) ?: continue
reportErrors(callInfo, resolvedCall, errors)
}
for (call in oldDoubleColonExpressionCalls) {
when (call) {
is KtDoubleColonExpression -> completeDoubleColonExpression(call, nonFixedTypesToResultSubstitutor)
else -> throw Exception("Unsupported call expression type")
}
for (call in commonPartiallyResolvedCalls) {
val resolvedCall = completeCall(call, atomCompleter) ?: continue
reportErrors(call, resolvedCall, errors)
}
atomCompleter.completeAll(lambda)
@@ -28,7 +28,7 @@ abstract class StubTypesBasedInferenceSession<D : CallableDescriptor>(
protected val callComponents: KotlinCallComponents,
val builtIns: KotlinBuiltIns
) : InferenceSession {
protected val partiallyResolvedCallsInfo = arrayListOf<PSIPartialCallInfo>()
protected val commonPartiallyResolvedCalls = arrayListOf<PSIPartialCallInfo>()
val errorCallsInfo = arrayListOf<PSIErrorCallInfo<D>>()
private val completedCalls = hashSetOf<ResolvedAtom>()
protected val nestedInferenceSessions = hashSetOf<StubTypesBasedInferenceSession<*>>()
@@ -49,7 +49,7 @@ abstract class StubTypesBasedInferenceSession<D : CallableDescriptor>(
if (callInfo !is PSIPartialCallInfo) {
throw AssertionError("Call info for $callInfo should be instance of PSIPartialCallInfo")
}
partiallyResolvedCallsInfo.add(callInfo)
commonPartiallyResolvedCalls.add(callInfo)
}
override fun addCompletedCallInfo(callInfo: CompletedCallInfo) {
@@ -65,7 +65,7 @@ abstract class StubTypesBasedInferenceSession<D : CallableDescriptor>(
}
override fun currentConstraintSystem(): ConstraintStorage {
return partiallyResolvedCallsInfo.lastOrNull()?.callResolutionResult?.constraintSystem?.getBuilder()?.currentStorage()
return commonPartiallyResolvedCalls.lastOrNull()?.callResolutionResult?.constraintSystem?.getBuilder()?.currentStorage()
?: ConstraintStorage.Empty
}
@@ -75,7 +75,7 @@ abstract class StubTypesBasedInferenceSession<D : CallableDescriptor>(
override fun shouldCompleteResolvedSubAtomsOf(resolvedCallAtom: ResolvedCallAtom) = true
fun resolveCandidates(resolutionCallbacks: KotlinResolutionCallbacks): List<ResolutionResultCallInfo<D>> {
val resolvedCallsInfo = partiallyResolvedCallsInfo.toList()
val resolvedCallsInfo = commonPartiallyResolvedCalls.toList()
val diagnosticHolder = KotlinDiagnosticsHolder.SimpleHolder()
@@ -111,7 +111,7 @@ class DoubleColonExpressionResolver(
val result = resolveDoubleColonLHS(expression, c)
if (c.inferenceSession is BuilderInferenceSession && result?.type?.contains { it is StubTypeForBuilderInference } == true) {
c.inferenceSession.addOldCallableReferenceCalls(expression)
c.inferenceSession.addExpression(expression)
}
if (result != null && !result.type.isError) {
@@ -557,7 +557,7 @@ class DoubleColonExpressionResolver(
val dataFlowInfo = (lhs as? DoubleColonLHS.Expression)?.dataFlowInfo ?: c.dataFlowInfo
if (c.inferenceSession is BuilderInferenceSession && result?.contains { it is StubTypeForBuilderInference } == true) {
c.inferenceSession.addOldCallableReferenceCalls(expression)
c.inferenceSession.addExpression(expression)
}
return dataFlowAnalyzer.checkType(createTypeInfo(result, dataFlowInfo), expression, c)
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getAnnotationEntries
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.BindingContext.EXPECTED_RETURN_TYPE
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
import org.jetbrains.kotlin.resolve.calls.inference.BuilderInferenceSession
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableTypeConstructor
import org.jetbrains.kotlin.resolve.checkers.TrailingCommaChecker
import org.jetbrains.kotlin.resolve.checkers.UnderscoreChecker
@@ -182,6 +183,10 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre
functionDescriptor.createFunctionType(components.builtIns, suspendFunctionTypeExpected)!!
)
if (context.inferenceSession is BuilderInferenceSession) {
context.inferenceSession.addExpression(expression)
}
if (functionTypeExpected) {
// all checks were done before
return createTypeInfo(resultType, context)
@@ -0,0 +1,11 @@
// WITH_STDLIB
// IGNORE_BACKEND_FIR: JVM_IR
// FIR status: different behavour with FE 1.0, reported `NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER`
fun box(): String {
buildList {
val foo = { first() }
add(0, foo)
}
return "OK"
}
@@ -19096,6 +19096,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/inference/builderInference/kt49887.kt");
}
@Test
@TestMetadata("kt50520.kt")
public void testKt50520() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/kt50520.kt");
}
@Test
@TestMetadata("kt51988.kt")
public void testKt51988() throws Exception {
@@ -19558,6 +19558,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/inference/builderInference/kt49887.kt");
}
@Test
@TestMetadata("kt50520.kt")
public void testKt50520() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/kt50520.kt");
}
@Test
@TestMetadata("kt51988.kt")
public void testKt51988() throws Exception {
@@ -15868,6 +15868,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/inference/builderInference/kt49887.kt");
}
@TestMetadata("kt50520.kt")
public void testKt50520() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/kt50520.kt");
}
@TestMetadata("kt51988.kt")
public void testKt51988() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/kt51988.kt");
@@ -14856,6 +14856,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inference/builderInference/kt49887.kt");
}
@Test
@TestMetadata("kt50520.kt")
public void testKt50520() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/kt50520.kt");
}
@Test
@TestMetadata("kt51988.kt")
public void testKt51988() throws Exception {
@@ -14820,6 +14820,12 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inference/builderInference/kt49887.kt");
}
@Test
@TestMetadata("kt50520.kt")
public void testKt50520() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/kt50520.kt");
}
@Test
@TestMetadata("kt51988.kt")
public void testKt51988() throws Exception {
@@ -13188,6 +13188,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
runTest("compiler/testData/codegen/box/inference/builderInference/kt49887.kt");
}
@TestMetadata("kt50520.kt")
public void testKt50520() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/kt50520.kt");
}
@TestMetadata("kt51988.kt")
public void testKt51988() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/kt51988.kt");
@@ -15948,6 +15948,12 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
runTest("compiler/testData/codegen/box/inference/builderInference/kt49887.kt");
}
@Test
@TestMetadata("kt50520.kt")
public void testKt50520() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/kt50520.kt");
}
@Test
@TestMetadata("kt51988.kt")
public void testKt51988() throws Exception {