[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.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.expressions.DataFlowAnalyzer
|
||||
import java.util.*
|
||||
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.descriptors.CallableDescriptor
|
||||
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.KtPsiUtil
|
||||
import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.calls.components.LambdaAnalyzer
|
||||
import org.jetbrains.kotlin.types.TypeApproximator
|
||||
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
|
||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCall
|
||||
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.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.util.CallMaker
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
|
||||
@@ -94,4 +94,16 @@ class LambdaAnalyzerImpl(
|
||||
override fun bindStubResolvedCallForCandidate(candidate: KotlinResolutionCandidate) {
|
||||
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()
|
||||
|
||||
return if (context.contextDependency == ContextDependency.DEPENDENT) {
|
||||
assert(expectedType == TypeUtils.NO_EXPECTED_TYPE)
|
||||
assert(TypeUtils.noExpectedType(expectedType)) {
|
||||
"Should have no expected type, got: $expectedType"
|
||||
}
|
||||
null
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -366,6 +366,11 @@ public class CallMaker {
|
||||
public CallType getCallType() {
|
||||
return CallType.DEFAULT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return DebugTextUtilKt.getDebugText(callElement);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -100,4 +100,9 @@ public class DelegatingCall implements Call {
|
||||
public CallType 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
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ class KotlinCallResolver(
|
||||
}
|
||||
|
||||
return maximallySpecificCandidates.map {
|
||||
kotlinCallCompleter.transformWhenAmbiguity(it)
|
||||
kotlinCallCompleter.transformWhenAmbiguity(it, callContext.lambdaAnalyzer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -17,10 +17,8 @@
|
||||
package org.jetbrains.kotlin.resolve.calls.components
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCall
|
||||
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.model.*
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
|
||||
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
|
||||
fun bindStubResolvedCallForCandidate(candidate: KotlinResolutionCandidate)
|
||||
|
||||
fun completeLambdaReturnType(lambdaArgument: ResolvedLambdaArgument, returnType: KotlinType)
|
||||
|
||||
}
|
||||
+8
-4
@@ -63,8 +63,8 @@ class KotlinCallCompleter(
|
||||
fun getBuilder(): ConstraintSystemBuilder
|
||||
}
|
||||
|
||||
fun transformWhenAmbiguity(candidate: KotlinResolutionCandidate): ResolvedKotlinCall =
|
||||
toCompletedBaseResolvedCall(candidate.lastCall.constraintSystem.asCallCompleterContext(), candidate)
|
||||
fun transformWhenAmbiguity(candidate: KotlinResolutionCandidate, lambdaAnalyzer: LambdaAnalyzer): ResolvedKotlinCall =
|
||||
toCompletedBaseResolvedCall(candidate.lastCall.constraintSystem.asCallCompleterContext(), candidate, lambdaAnalyzer)
|
||||
|
||||
fun completeCallIfNecessary(
|
||||
candidate: KotlinResolutionCandidate,
|
||||
@@ -82,7 +82,7 @@ class KotlinCallCompleter(
|
||||
val c = candidate.lastCall.constraintSystem.asCallCompleterContext()
|
||||
|
||||
topLevelCall.competeCall(c, lambdaAnalyzer)
|
||||
return toCompletedBaseResolvedCall(c, candidate)
|
||||
return toCompletedBaseResolvedCall(c, candidate, lambdaAnalyzer)
|
||||
}
|
||||
|
||||
return ResolvedKotlinCall.OnlyResolvedKotlinCall(candidate)
|
||||
@@ -90,13 +90,17 @@ class KotlinCallCompleter(
|
||||
|
||||
private fun toCompletedBaseResolvedCall(
|
||||
c: Context,
|
||||
candidate: KotlinResolutionCandidate
|
||||
candidate: KotlinResolutionCandidate,
|
||||
lambdaAnalyzer: LambdaAnalyzer
|
||||
): ResolvedKotlinCall.CompletedResolvedKotlinCall {
|
||||
val currentSubstitutor = c.buildResultingSubstitutor()
|
||||
val completedCall = candidate.toCompletedCall(currentSubstitutor)
|
||||
val competedCalls = c.innerCalls.map {
|
||||
it.candidate.toCompletedCall(currentSubstitutor)
|
||||
}
|
||||
c.lambdaArguments.forEach {
|
||||
lambdaAnalyzer.completeLambdaReturnType(it, currentSubstitutor.safeSubstitute(it.returnType))
|
||||
}
|
||||
return ResolvedKotlinCall.CompletedResolvedKotlinCall(completedCall, competedCalls)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user