diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ArgumentTypeResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ArgumentTypeResolver.java index d86ece87f85..4539cd7cfe9 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ArgumentTypeResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ArgumentTypeResolver.java @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.name.SpecialNames; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.BindingTrace; +import org.jetbrains.kotlin.resolve.StatementFilter; import org.jetbrains.kotlin.resolve.TemporaryBindingTrace; import org.jetbrains.kotlin.resolve.TypeResolver; import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode; @@ -398,12 +399,22 @@ public class ArgumentTypeResolver { @NotNull ResolutionContext context, @NotNull KtExpression expression ) { - KotlinType type = context.trace.getType(expression); + return updateResultArgumentTypeIfNotDenotable(context.trace, context.statementFilter, context.expectedType, expression); + } + + @Nullable + public KotlinType updateResultArgumentTypeIfNotDenotable( + @NotNull BindingTrace trace, + @NotNull StatementFilter statementFilter, + @NotNull KotlinType expectedType, + @NotNull KtExpression expression + ) { + KotlinType type = trace.getType(expression); if (type != null && !type.getConstructor().isDenotable()) { if (type.getConstructor() instanceof IntegerValueTypeConstructor) { IntegerValueTypeConstructor constructor = (IntegerValueTypeConstructor) type.getConstructor(); - KotlinType primitiveType = TypeUtils.getPrimitiveNumberType(constructor, context.expectedType); - constantExpressionEvaluator.updateNumberType(primitiveType, expression, context.statementFilter, context.trace); + KotlinType primitiveType = TypeUtils.getPrimitiveNumberType(constructor, expectedType); + constantExpressionEvaluator.updateNumberType(primitiveType, expression, statementFilter, trace); return primitiveType; } } 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 3284af6b230..dccdbffc752 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 @@ -27,16 +27,13 @@ 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.ArgumentTypeResolver 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.* 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.* import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo @@ -44,10 +41,11 @@ class LambdaAnalyzerImpl( val expressionTypingServices: ExpressionTypingServices, val trace: BindingTrace, val typeApproximator: TypeApproximator, - val kotlinToResolvedCallTransformer: KotlinToResolvedCallTransformer + val kotlinToResolvedCallTransformer: KotlinToResolvedCallTransformer, + val argumentTypeResolver: ArgumentTypeResolver ): LambdaAnalyzer { - override fun analyzeAndGetRelatedCalls( + override fun analyzeAndGetLambdaResultArguments( topLevelCall: KotlinCall, lambdaArgument: LambdaKotlinCallArgument, receiverType: UnwrappedType?, @@ -102,8 +100,21 @@ class LambdaAnalyzerImpl( 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) + + for (lambdaResult in lambdaArgument.resultArguments) { + val resultValueArgument = lambdaResult.psiCallArgument.valueArgument + val deparenthesized = resultValueArgument.getArgumentExpression()?.let { + KtPsiUtil.getLastElementDeparenthesized(it, expressionTypingServices.statementFilter) + } ?: continue + + val recordedType = trace.getType(deparenthesized) + if (recordedType != null && !recordedType.constructor.isDenotable) { + argumentTypeResolver.updateResultArgumentTypeIfNotDenotable(trace, expressionTypingServices.statementFilter, returnType, deparenthesized) + } + } } } \ 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 f9c5fae0751..f1ae8d5155d 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 @@ -77,7 +77,8 @@ class PSICallResolver( val constraintInjector: ConstraintInjector, private val kotlinToResolvedCallTransformer: KotlinToResolvedCallTransformer, private val kotlinCallResolver: KotlinCallResolver, - private val typeApproximator: TypeApproximator + private val typeApproximator: TypeApproximator, + private val argumentTypeResolver: ArgumentTypeResolver ) { private val GIVEN_CANDIDATES_NAME = Name.special("") @@ -89,7 +90,7 @@ class PSICallResolver( ) : OverloadResolutionResults { val kotlinCall = toKotlinCall(context, resolutionKind.kotlinCallKind, context.call, name, tracingStrategy) val scopeTower = ASTScopeTower(context) - val lambdaAnalyzer = LambdaAnalyzerImpl(expressionTypingServices, context.trace, typeApproximator, kotlinToResolvedCallTransformer) + val lambdaAnalyzer = createLambdaAnalyzer(context) val callContext = createCallContext(scopeTower, lambdaAnalyzer) val factoryProviderForInvoke = FactoryProviderForInvoke(context, callContext, kotlinCall) @@ -112,7 +113,7 @@ class PSICallResolver( val kotlinCall = toKotlinCall(context, KotlinCallKind.FUNCTION, context.call, GIVEN_CANDIDATES_NAME, tracingStrategy, dispatchReceiver) val scopeTower = ASTScopeTower(context) - val lambdaAnalyzer = LambdaAnalyzerImpl(expressionTypingServices, context.trace, typeApproximator, kotlinToResolvedCallTransformer) + val lambdaAnalyzer = createLambdaAnalyzer(context) val callContext = createCallContext(scopeTower, lambdaAnalyzer) val givenCandidates = resolutionCandidates.map { @@ -126,6 +127,9 @@ class PSICallResolver( } + private fun createLambdaAnalyzer(context: BasicCallResolutionContext) = + LambdaAnalyzerImpl(expressionTypingServices, context.trace, typeApproximator, kotlinToResolvedCallTransformer, argumentTypeResolver) + private fun calculateExpectedType(context: BasicCallResolutionContext): UnwrappedType? { val expectedType = context.expectedType.unwrap() 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 194d19a70a8..9494550491c 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 @@ -26,7 +26,7 @@ interface IsDescriptorFromSourcePredicate: (CallableDescriptor) -> Boolean interface CommonSupertypeCalculator: (Collection) -> UnwrappedType interface LambdaAnalyzer { - fun analyzeAndGetRelatedCalls( + fun analyzeAndGetLambdaResultArguments( topLevelCall: KotlinCall, lambdaArgument: LambdaKotlinCallArgument, receiverType: UnwrappedType?, 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 81690f3ec90..cc93e2c402d 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 @@ -245,10 +245,10 @@ class KotlinCallCompleter( val receiver = lambda.receiver?.let(::substitute) val parameters = lambda.parameters.map(::substitute) val expectedType = lambda.returnType.takeIf { c.canBeProper(it) }?.let(::substitute) - val callsFromLambda = lambdaAnalyzer.analyzeAndGetRelatedCalls(topLevelCall, lambda.argument, receiver, parameters, expectedType) lambda.analyzed = true + lambda.resultArguments = lambdaAnalyzer.analyzeAndGetLambdaResultArguments(topLevelCall, lambda.argument, receiver, parameters, expectedType) - for (innerCall in callsFromLambda) { + for (innerCall in lambda.resultArguments) { // todo strange code -- why top-level kotlinCall? may be it isn't right outer call CheckArguments.checkArgument(topLevelCallContext, topLevelCall, c.getBuilder(), innerCall, lambda.returnType) } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolvedCallElements.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolvedCallElements.kt index d2594f352ca..bd78cd00a19 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolvedCallElements.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolvedCallElements.kt @@ -51,6 +51,8 @@ class ResolvedLambdaArgument( override val inputType: Collection get() = receiver?.let { parameters + it } ?: parameters override val outputType: UnwrappedType get() = returnType + + lateinit var resultArguments: List }