From f47c3f0f5a186536d2ab5e6eaa644152f57e9d1d Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Thu, 26 Dec 2019 14:59:16 +0300 Subject: [PATCH] FIR: if necessary, use explicit receiver as argument in invoke collector --- .../fir/resolve/calls/CandidateCollector.kt | 19 +++++++++++++++---- .../expresssions/invoke/inBrackets.txt | 4 ++-- .../invoke/propertyWithExtensionType.txt | 4 ++-- .../expresssions/lambdaWithReceiver.txt | 4 ++-- .../testData/resolve/functionTypes.txt | 2 +- .../problems/invokeOfLambdaWithReceiver.txt | 2 +- 6 files changed, 23 insertions(+), 12 deletions(-) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateCollector.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateCollector.kt index f796ccbac0f..7f3477071cd 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateCollector.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateCollector.kt @@ -5,11 +5,14 @@ package org.jetbrains.kotlin.fir.resolve.calls +import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression import org.jetbrains.kotlin.fir.expressions.impl.FirQualifiedAccessExpressionImpl import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents import org.jetbrains.kotlin.fir.resolve.transformQualifiedAccessUsingSmartcastInfo import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol +import org.jetbrains.kotlin.fir.types.isExtensionFunctionType +import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.util.OperatorNameConventions open class CandidateCollector( @@ -80,16 +83,21 @@ class InvokeReceiverCandidateCollector( val applicability = super.consumeCandidate(group, candidate) if (applicability >= CandidateApplicability.SYNTHETIC_RESOLVED) { - val session = components.session + val symbol = candidate.symbol as FirCallableSymbol<*> + val extensionReceiverExpression = candidate.extensionReceiverExpression() + val useExtensionReceiverAsArgument = + symbol.fir.receiverTypeRef == null && + candidate.explicitReceiverKind == ExplicitReceiverKind.EXTENSION_RECEIVER && + symbol.fir.returnTypeRef.isExtensionFunctionType() val explicitReceiver = FirQualifiedAccessExpressionImpl(null).apply { calleeReference = FirNamedReferenceWithCandidate( null, - (candidate.symbol as FirCallableSymbol<*>).callableId.callableName, + symbol.callableId.callableName, candidate ) dispatchReceiver = candidate.dispatchReceiverExpression() - extensionReceiver = candidate.extensionReceiverExpression() + extensionReceiver = extensionReceiverExpression.takeIf { !useExtensionReceiverAsArgument } ?: FirNoReceiverExpression typeRef = towerResolver.typeCalculator.tryCalculateReturnType(candidate.symbol.firUnsafe()) }.let { components.transformQualifiedAccessUsingSmartcastInfo(it) @@ -107,7 +115,10 @@ class InvokeReceiverCandidateCollector( invokeCallInfo.outerCSBuilder, invokeCallInfo.lhs, invokeCallInfo.typeProvider - ) + ).let { + if (useExtensionReceiverAsArgument) it.withReceiverAsArgument(extensionReceiverExpression) + else it + } invokeConsumer.addConsumerAndProcessAccumulatedData( createSimpleFunctionConsumer( diff --git a/compiler/fir/resolve/testData/resolve/expresssions/invoke/inBrackets.txt b/compiler/fir/resolve/testData/resolve/expresssions/invoke/inBrackets.txt index 6a1cd22f4f3..76ef1884c37 100644 --- a/compiler/fir/resolve/testData/resolve/expresssions/invoke/inBrackets.txt +++ b/compiler/fir/resolve/testData/resolve/expresssions/invoke/inBrackets.txt @@ -1,5 +1,5 @@ FILE: inBrackets.kt public final fun test(e: R|kotlin/Int.() -> kotlin/String|): R|kotlin/Unit| { - lval s: R|kotlin/String| = Int(3).R|/e|.R|FakeOverride|(Int(3)) - lval ss: R|kotlin/String| = Int(3).R|/e|.R|FakeOverride|(Int(3)) + lval s: R|kotlin/String| = R|/e|.R|FakeOverride|(Int(3)) + lval ss: R|kotlin/String| = R|/e|.R|FakeOverride|(Int(3)) } diff --git a/compiler/fir/resolve/testData/resolve/expresssions/invoke/propertyWithExtensionType.txt b/compiler/fir/resolve/testData/resolve/expresssions/invoke/propertyWithExtensionType.txt index 8a80f9ae8c5..0902da269bd 100644 --- a/compiler/fir/resolve/testData/resolve/expresssions/invoke/propertyWithExtensionType.txt +++ b/compiler/fir/resolve/testData/resolve/expresssions/invoke/propertyWithExtensionType.txt @@ -15,10 +15,10 @@ FILE: propertyWithExtensionType.kt when () { !=(R|/a|.R|/A.x|, Null(null)) -> { lval b: R|kotlin/String.() -> kotlin/Unit| = R|/a|.R|/A.x| - String().R|/b|.R|FakeOverride|(String()) + R|/b|.R|FakeOverride|(String()) } } lval c: R|kotlin/String.() -> kotlin/Int| = R|/a|.R|/A.y| - lval d: R|kotlin/Int| = String().R|/c|.R|FakeOverride|(String()) + lval d: R|kotlin/Int| = R|/c|.R|FakeOverride|(String()) } diff --git a/compiler/fir/resolve/testData/resolve/expresssions/lambdaWithReceiver.txt b/compiler/fir/resolve/testData/resolve/expresssions/lambdaWithReceiver.txt index 375e49e6a13..4af38c4dd2e 100644 --- a/compiler/fir/resolve/testData/resolve/expresssions/lambdaWithReceiver.txt +++ b/compiler/fir/resolve/testData/resolve/expresssions/lambdaWithReceiver.txt @@ -4,10 +4,10 @@ FILE: lambdaWithReceiver.kt } public final fun myWith(receiver: R|T|, block: R|T.() -> kotlin/Unit|): R|kotlin/Unit| { - R|/receiver|.R|/block|.R|FakeOverride|(R|/receiver|) + R|/block|.R|FakeOverride|(R|/receiver|) } public final fun R|T|.myApply(block: R|T.() -> kotlin/Unit|): R|kotlin/Unit| { - this@R|/myApply|.R|/block|.R|FakeOverride|(this@R|/myApply|) + R|/block|.R|FakeOverride|(this@R|/myApply|) } public final fun withA(block: R|A.() -> kotlin/Unit|): R|kotlin/Unit| { } diff --git a/compiler/fir/resolve/testData/resolve/functionTypes.txt b/compiler/fir/resolve/testData/resolve/functionTypes.txt index 5975a07a19a..78bdd7e25cd 100644 --- a/compiler/fir/resolve/testData/resolve/functionTypes.txt +++ b/compiler/fir/resolve/testData/resolve/functionTypes.txt @@ -5,7 +5,7 @@ FILE: functionTypes.kt public final fun R|kotlin/collections/List|.simpleMap(f: R|(T) -> R|): R|R| { } public final fun simpleWith(t: R|T|, f: R|T.() -> kotlin/Unit|): R|kotlin/Unit| { - ^simpleWith R|/t|.R|/f|.R|FakeOverride|(R|/t|) + ^simpleWith R|/f|.R|FakeOverride|(R|/t|) } public abstract interface KMutableProperty1 : R|KProperty1|, R|KMutableProperty| { } diff --git a/compiler/fir/resolve/testData/resolve/problems/invokeOfLambdaWithReceiver.txt b/compiler/fir/resolve/testData/resolve/problems/invokeOfLambdaWithReceiver.txt index fabedb09b12..5ca57c3f38d 100644 --- a/compiler/fir/resolve/testData/resolve/problems/invokeOfLambdaWithReceiver.txt +++ b/compiler/fir/resolve/testData/resolve/problems/invokeOfLambdaWithReceiver.txt @@ -2,7 +2,7 @@ FILE: invokeOfLambdaWithReceiver.kt public abstract interface A : R|kotlin/Any| { } public final fun test(a: R|A|, block: R|A.() -> kotlin/Int|): R|kotlin/Unit| { - R|/a|.R|/block|.R|FakeOverride|(R|/a|) + R|/block|.R|FakeOverride|(R|/a|) } public abstract interface B : R|kotlin/Any| { }