From 971b02494c1cb9d21dbbf408e584250c344d64dc Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Tue, 17 Sep 2019 13:22:42 +0300 Subject: [PATCH] [NI] Minor, simplify code a bit for sub calls preparation --- .../resolve/calls/tower/NewCallArguments.kt | 34 ++++++++++------- .../resolve/calls/tower/PSICallResolver.kt | 37 +++++++++++-------- 2 files changed, 41 insertions(+), 30 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt index cba94ee2ae7..3e6ea7a5655 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt @@ -294,30 +294,36 @@ internal fun createSimplePSICallArgument( ): SimplePSIKotlinCallArgument? { val ktExpression = KtPsiUtil.getLastElementDeparenthesized(valueArgument.getArgumentExpression(), statementFilter) ?: return null - val onlyResolvedCall = ktExpression.getCall(bindingContext)?.let { + val partiallyResolvedCall = ktExpression.getCall(bindingContext)?.let { bindingContext.get(BindingContext.ONLY_RESOLVED_CALL, it)?.result } // todo hack for if expression: sometimes we not write properly type information for branches - val baseType = typeInfoForArgument.type?.unwrap() ?: onlyResolvedCall?.resultCallAtom?.freshReturnType ?: return null + val baseType = typeInfoForArgument.type?.unwrap() ?: partiallyResolvedCall?.resultCallAtom?.freshReturnType ?: return null + + val expressionReceiver = ExpressionReceiver.create(ktExpression, baseType, bindingContext) + // For a sub-call there can't be any smartcast so we use a fast-path here to avoid calling transformToReceiverWithSmartCastInfo function + if (partiallyResolvedCall != null) { + val capturedReceiver = + ReceiverValueWithSmartCastInfo(expressionReceiver, emptySet(), isStable = true) + .prepareReceiverRegardingCaptureTypes() + + return SubKotlinCallArgumentImpl( + valueArgument, + dataFlowInfoBeforeThisArgument, + typeInfoForArgument.dataFlowInfo, + capturedReceiver, + partiallyResolvedCall + ) + } // we should use DFI after this argument, because there can be some useful smartcast. Popular case: if branches. val receiverToCast = transformToReceiverWithSmartCastInfo( ownerDescriptor, bindingContext, typeInfoForArgument.dataFlowInfo, // dataFlowInfoBeforeThisArgument cannot be used here, because of if() { if (x != null) return; x } - ExpressionReceiver.create(ktExpression, baseType, bindingContext), + expressionReceiver, languageVersionSettings, dataFlowValueFactory ).prepareReceiverRegardingCaptureTypes() - return if (onlyResolvedCall == null) { - ExpressionKotlinCallArgumentImpl(valueArgument, dataFlowInfoBeforeThisArgument, typeInfoForArgument.dataFlowInfo, receiverToCast) - } else { - SubKotlinCallArgumentImpl( - valueArgument, - dataFlowInfoBeforeThisArgument, - typeInfoForArgument.dataFlowInfo, - receiverToCast, - onlyResolvedCall - ) - } + return ExpressionKotlinCallArgumentImpl(valueArgument, dataFlowInfoBeforeThisArgument, typeInfoForArgument.dataFlowInfo, receiverToCast) } 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 82a956c5b55..9f119bcd66a 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 @@ -579,37 +579,42 @@ class PSICallResolver( oldReceiver: Receiver?, isSafeCall: Boolean, isForImplicitInvoke: Boolean - ): ReceiverKotlinCallArgument? = - when (oldReceiver) { + ): ReceiverKotlinCallArgument? { + return when (oldReceiver) { null -> null - is QualifierReceiver -> QualifierReceiverKotlinCallArgument(oldReceiver) // todo report warning if isSafeCall - is ReceiverValue -> { - val detailedReceiver = context.transformToReceiverWithSmartCastInfo(oldReceiver) - var subCallArgument: ReceiverKotlinCallArgument? = null + is QualifierReceiver -> QualifierReceiverKotlinCallArgument(oldReceiver) // todo report warning if isSafeCall + + is ReceiverValue -> { if (oldReceiver is ExpressionReceiver) { val ktExpression = KtPsiUtil.getLastElementDeparenthesized(oldReceiver.expression, context.statementFilter) val bindingContext = context.trace.bindingContext - val call = bindingContext[BindingContext.DELEGATE_EXPRESSION_TO_PROVIDE_DELEGATE_CALL, ktExpression] - ?: ktExpression?.getCall(bindingContext) + val call = + bindingContext[BindingContext.DELEGATE_EXPRESSION_TO_PROVIDE_DELEGATE_CALL, ktExpression] + ?: ktExpression?.getCall(bindingContext) - val onlyResolvedCall = call?.let { - bindingContext.get(BindingContext.ONLY_RESOLVED_CALL, it)?.result - } - if (onlyResolvedCall != null) { - subCallArgument = SubKotlinCallArgumentImpl( + val partiallyResolvedCall = call?.let { bindingContext.get(BindingContext.ONLY_RESOLVED_CALL, it)?.result } + + if (partiallyResolvedCall != null) { + val receiver = ReceiverValueWithSmartCastInfo(oldReceiver, emptySet(), isStable = true) + return SubKotlinCallArgumentImpl( CallMaker.makeExternalValueArgument(oldReceiver.expression), - context.dataFlowInfo, context.dataFlowInfo, detailedReceiver, onlyResolvedCall + context.dataFlowInfo, context.dataFlowInfo, receiver, partiallyResolvedCall ) - } } - subCallArgument ?: ReceiverExpressionKotlinCallArgument(detailedReceiver, isSafeCall, isForImplicitInvoke) + ReceiverExpressionKotlinCallArgument( + context.transformToReceiverWithSmartCastInfo(oldReceiver), + isSafeCall, + isForImplicitInvoke + ) } + else -> error("Incorrect receiver: $oldReceiver") } + } private fun resolveTypeArguments(context: BasicCallResolutionContext, typeArguments: List): List = typeArguments.map { projection ->