[NI] Update lambda result types.
When completing calls, update return types for functional descriptors for lambdas using type inference results. Add toString to some Call subclasses (for debugging purposes).
This commit is contained in:
committed by
Stanislav Erokhin
parent
2bf252afe6
commit
1d6ed4ef8e
-1
@@ -43,7 +43,6 @@ import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluat
|
|||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.types.UnwrappedType
|
|
||||||
import org.jetbrains.kotlin.types.expressions.DataFlowAnalyzer
|
import org.jetbrains.kotlin.types.expressions.DataFlowAnalyzer
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.HashMap
|
import kotlin.collections.HashMap
|
||||||
|
|||||||
+16
-4
@@ -21,20 +21,20 @@ import org.jetbrains.kotlin.builtins.getReturnTypeFromFunctionType
|
|||||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
import org.jetbrains.kotlin.psi.KtPsiUtil
|
import org.jetbrains.kotlin.psi.KtPsiUtil
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis
|
import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||||
import org.jetbrains.kotlin.resolve.calls.components.LambdaAnalyzer
|
import org.jetbrains.kotlin.resolve.calls.components.LambdaAnalyzer
|
||||||
import org.jetbrains.kotlin.types.TypeApproximator
|
import org.jetbrains.kotlin.types.TypeApproximator
|
||||||
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
|
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
|
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCall
|
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallArgument
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinResolutionCandidate
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.LambdaKotlinCallArgument
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.util.CallMaker
|
import org.jetbrains.kotlin.resolve.calls.util.CallMaker
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.types.UnwrappedType
|
import org.jetbrains.kotlin.types.UnwrappedType
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
|
||||||
@@ -94,4 +94,16 @@ class LambdaAnalyzerImpl(
|
|||||||
override fun bindStubResolvedCallForCandidate(candidate: KotlinResolutionCandidate) {
|
override fun bindStubResolvedCallForCandidate(candidate: KotlinResolutionCandidate) {
|
||||||
kotlinToResolvedCallTransformer.createStubResolvedCallAndWriteItToTrace<CallableDescriptor>(candidate, trace)
|
kotlinToResolvedCallTransformer.createStubResolvedCallAndWriteItToTrace<CallableDescriptor>(candidate, trace)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun completeLambdaReturnType(lambdaArgument: ResolvedLambdaArgument, returnType: KotlinType) {
|
||||||
|
val psiCallArgument = lambdaArgument.argument.psiCallArgument
|
||||||
|
val ktFunction = when (psiCallArgument) {
|
||||||
|
is LambdaKotlinCallArgumentImpl -> psiCallArgument.ktLambdaExpression.functionLiteral
|
||||||
|
is FunctionExpressionImpl -> psiCallArgument.ktFunction
|
||||||
|
else -> throw AssertionError("Unexpected psiCallArgument for resolved lambda argument: $psiCallArgument")
|
||||||
|
}
|
||||||
|
val functionDescriptor = trace.bindingContext.get(BindingContext.FUNCTION, ktFunction) as? FunctionDescriptorImpl ?:
|
||||||
|
throw AssertionError("No function descriptor for resolved lambda argument")
|
||||||
|
functionDescriptor.setReturnType(returnType)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -130,7 +130,9 @@ class PSICallResolver(
|
|||||||
val expectedType = context.expectedType.unwrap()
|
val expectedType = context.expectedType.unwrap()
|
||||||
|
|
||||||
return if (context.contextDependency == ContextDependency.DEPENDENT) {
|
return if (context.contextDependency == ContextDependency.DEPENDENT) {
|
||||||
assert(expectedType == TypeUtils.NO_EXPECTED_TYPE)
|
assert(TypeUtils.noExpectedType(expectedType)) {
|
||||||
|
"Should have no expected type, got: $expectedType"
|
||||||
|
}
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -366,6 +366,11 @@ public class CallMaker {
|
|||||||
public CallType getCallType() {
|
public CallType getCallType() {
|
||||||
return CallType.DEFAULT;
|
return CallType.DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return DebugTextUtilKt.getDebugText(callElement);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -100,4 +100,9 @@ public class DelegatingCall implements Call {
|
|||||||
public CallType getCallType() {
|
public CallType getCallType() {
|
||||||
return delegate.getCallType();
|
return delegate.getCallType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "*" + delegate.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-2
@@ -220,8 +220,10 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre
|
|||||||
|
|
||||||
// This is needed for ControlStructureTypingVisitor#visitReturnExpression() to properly type-check returned expressions
|
// This is needed for ControlStructureTypingVisitor#visitReturnExpression() to properly type-check returned expressions
|
||||||
context.trace.record(EXPECTED_RETURN_TYPE, functionLiteral, expectedType)
|
context.trace.record(EXPECTED_RETURN_TYPE, functionLiteral, expectedType)
|
||||||
val typeOfBodyExpression = // Type-check the body
|
|
||||||
components.expressionTypingServices.getBlockReturnedType(functionLiteral.bodyExpression!!, COERCION_TO_UNIT, newContext).type
|
// Type-check the body
|
||||||
|
val blockReturnedType = components.expressionTypingServices.getBlockReturnedType(functionLiteral.bodyExpression!!, COERCION_TO_UNIT, newContext)
|
||||||
|
val typeOfBodyExpression = blockReturnedType.type
|
||||||
|
|
||||||
return computeReturnTypeBasedOnReturnExpressions(functionLiteral, context, typeOfBodyExpression)
|
return computeReturnTypeBasedOnReturnExpressions(functionLiteral, context, typeOfBodyExpression)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ class KotlinCallResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return maximallySpecificCandidates.map {
|
return maximallySpecificCandidates.map {
|
||||||
kotlinCallCompleter.transformWhenAmbiguity(it)
|
kotlinCallCompleter.transformWhenAmbiguity(it, callContext.lambdaAnalyzer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -17,10 +17,8 @@
|
|||||||
package org.jetbrains.kotlin.resolve.calls.components
|
package org.jetbrains.kotlin.resolve.calls.components
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCall
|
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallArgument
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinResolutionCandidate
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.LambdaKotlinCallArgument
|
|
||||||
import org.jetbrains.kotlin.types.UnwrappedType
|
import org.jetbrains.kotlin.types.UnwrappedType
|
||||||
|
|
||||||
interface IsDescriptorFromSourcePredicate: (CallableDescriptor) -> Boolean
|
interface IsDescriptorFromSourcePredicate: (CallableDescriptor) -> Boolean
|
||||||
@@ -39,4 +37,6 @@ interface LambdaAnalyzer {
|
|||||||
// todo this is hack for some client which try to read ResolvedCall from trace before all calls completed
|
// todo this is hack for some client which try to read ResolvedCall from trace before all calls completed
|
||||||
fun bindStubResolvedCallForCandidate(candidate: KotlinResolutionCandidate)
|
fun bindStubResolvedCallForCandidate(candidate: KotlinResolutionCandidate)
|
||||||
|
|
||||||
|
fun completeLambdaReturnType(lambdaArgument: ResolvedLambdaArgument, returnType: KotlinType)
|
||||||
|
|
||||||
}
|
}
|
||||||
+8
-4
@@ -63,8 +63,8 @@ class KotlinCallCompleter(
|
|||||||
fun getBuilder(): ConstraintSystemBuilder
|
fun getBuilder(): ConstraintSystemBuilder
|
||||||
}
|
}
|
||||||
|
|
||||||
fun transformWhenAmbiguity(candidate: KotlinResolutionCandidate): ResolvedKotlinCall =
|
fun transformWhenAmbiguity(candidate: KotlinResolutionCandidate, lambdaAnalyzer: LambdaAnalyzer): ResolvedKotlinCall =
|
||||||
toCompletedBaseResolvedCall(candidate.lastCall.constraintSystem.asCallCompleterContext(), candidate)
|
toCompletedBaseResolvedCall(candidate.lastCall.constraintSystem.asCallCompleterContext(), candidate, lambdaAnalyzer)
|
||||||
|
|
||||||
fun completeCallIfNecessary(
|
fun completeCallIfNecessary(
|
||||||
candidate: KotlinResolutionCandidate,
|
candidate: KotlinResolutionCandidate,
|
||||||
@@ -82,7 +82,7 @@ class KotlinCallCompleter(
|
|||||||
val c = candidate.lastCall.constraintSystem.asCallCompleterContext()
|
val c = candidate.lastCall.constraintSystem.asCallCompleterContext()
|
||||||
|
|
||||||
topLevelCall.competeCall(c, lambdaAnalyzer)
|
topLevelCall.competeCall(c, lambdaAnalyzer)
|
||||||
return toCompletedBaseResolvedCall(c, candidate)
|
return toCompletedBaseResolvedCall(c, candidate, lambdaAnalyzer)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResolvedKotlinCall.OnlyResolvedKotlinCall(candidate)
|
return ResolvedKotlinCall.OnlyResolvedKotlinCall(candidate)
|
||||||
@@ -90,13 +90,17 @@ class KotlinCallCompleter(
|
|||||||
|
|
||||||
private fun toCompletedBaseResolvedCall(
|
private fun toCompletedBaseResolvedCall(
|
||||||
c: Context,
|
c: Context,
|
||||||
candidate: KotlinResolutionCandidate
|
candidate: KotlinResolutionCandidate,
|
||||||
|
lambdaAnalyzer: LambdaAnalyzer
|
||||||
): ResolvedKotlinCall.CompletedResolvedKotlinCall {
|
): ResolvedKotlinCall.CompletedResolvedKotlinCall {
|
||||||
val currentSubstitutor = c.buildResultingSubstitutor()
|
val currentSubstitutor = c.buildResultingSubstitutor()
|
||||||
val completedCall = candidate.toCompletedCall(currentSubstitutor)
|
val completedCall = candidate.toCompletedCall(currentSubstitutor)
|
||||||
val competedCalls = c.innerCalls.map {
|
val competedCalls = c.innerCalls.map {
|
||||||
it.candidate.toCompletedCall(currentSubstitutor)
|
it.candidate.toCompletedCall(currentSubstitutor)
|
||||||
}
|
}
|
||||||
|
c.lambdaArguments.forEach {
|
||||||
|
lambdaAnalyzer.completeLambdaReturnType(it, currentSubstitutor.safeSubstitute(it.returnType))
|
||||||
|
}
|
||||||
return ResolvedKotlinCall.CompletedResolvedKotlinCall(completedCall, competedCalls)
|
return ResolvedKotlinCall.CompletedResolvedKotlinCall(completedCall, competedCalls)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user