diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt index 7d8fa76c7fe..8a984e00bcf 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt @@ -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 diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/LambdaAnalyzerImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/LambdaAnalyzerImpl.kt index cfe30df8100..3284af6b230 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/LambdaAnalyzerImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/LambdaAnalyzerImpl.kt @@ -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(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) + } } \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt index f17a7983e99..f9c5fae0751 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt @@ -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 { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/CallMaker.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/CallMaker.java index 36f12a4d7a0..27fc4953e52 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/CallMaker.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/CallMaker.java @@ -366,6 +366,11 @@ public class CallMaker { public CallType getCallType() { return CallType.DEFAULT; } + + @Override + public String toString() { + return DebugTextUtilKt.getDebugText(callElement); + } }; } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/DelegatingCall.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/DelegatingCall.java index 34cb78ac979..916e2732410 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/DelegatingCall.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/DelegatingCall.java @@ -100,4 +100,9 @@ public class DelegatingCall implements Call { public CallType getCallType() { return delegate.getCallType(); } + + @Override + public String toString() { + return "*" + delegate.toString(); + } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt index 196ba6cbfd9..9976434a596 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt @@ -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) } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/KotlinCallResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/KotlinCallResolver.kt index 2c072dec787..907f5f597fb 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/KotlinCallResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/KotlinCallResolver.kt @@ -102,7 +102,7 @@ class KotlinCallResolver( } return maximallySpecificCandidates.map { - kotlinCallCompleter.transformWhenAmbiguity(it) + kotlinCallCompleter.transformWhenAmbiguity(it, callContext.lambdaAnalyzer) } } } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt index a69802354f0..194d19a70a8 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt @@ -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) + } \ No newline at end of file diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt index eaaf7aa93e8..81690f3ec90 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt @@ -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) }