FIR: if necessary, use explicit receiver as argument in invoke collector

This commit is contained in:
Mikhail Glukhikh
2019-12-26 14:59:16 +03:00
parent 0c88ecdc56
commit f47c3f0f5a
6 changed files with 23 additions and 12 deletions
@@ -5,11 +5,14 @@
package org.jetbrains.kotlin.fir.resolve.calls 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.expressions.impl.FirQualifiedAccessExpressionImpl
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.transformQualifiedAccessUsingSmartcastInfo import org.jetbrains.kotlin.fir.resolve.transformQualifiedAccessUsingSmartcastInfo
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol 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 import org.jetbrains.kotlin.util.OperatorNameConventions
open class CandidateCollector( open class CandidateCollector(
@@ -80,16 +83,21 @@ class InvokeReceiverCandidateCollector(
val applicability = super.consumeCandidate(group, candidate) val applicability = super.consumeCandidate(group, candidate)
if (applicability >= CandidateApplicability.SYNTHETIC_RESOLVED) { if (applicability >= CandidateApplicability.SYNTHETIC_RESOLVED) {
val session = components.session 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 { val explicitReceiver = FirQualifiedAccessExpressionImpl(null).apply {
calleeReference = FirNamedReferenceWithCandidate( calleeReference = FirNamedReferenceWithCandidate(
null, null,
(candidate.symbol as FirCallableSymbol<*>).callableId.callableName, symbol.callableId.callableName,
candidate candidate
) )
dispatchReceiver = candidate.dispatchReceiverExpression() dispatchReceiver = candidate.dispatchReceiverExpression()
extensionReceiver = candidate.extensionReceiverExpression() extensionReceiver = extensionReceiverExpression.takeIf { !useExtensionReceiverAsArgument } ?: FirNoReceiverExpression
typeRef = towerResolver.typeCalculator.tryCalculateReturnType(candidate.symbol.firUnsafe()) typeRef = towerResolver.typeCalculator.tryCalculateReturnType(candidate.symbol.firUnsafe())
}.let { }.let {
components.transformQualifiedAccessUsingSmartcastInfo(it) components.transformQualifiedAccessUsingSmartcastInfo(it)
@@ -107,7 +115,10 @@ class InvokeReceiverCandidateCollector(
invokeCallInfo.outerCSBuilder, invokeCallInfo.outerCSBuilder,
invokeCallInfo.lhs, invokeCallInfo.lhs,
invokeCallInfo.typeProvider invokeCallInfo.typeProvider
) ).let {
if (useExtensionReceiverAsArgument) it.withReceiverAsArgument(extensionReceiverExpression)
else it
}
invokeConsumer.addConsumerAndProcessAccumulatedData( invokeConsumer.addConsumerAndProcessAccumulatedData(
createSimpleFunctionConsumer( createSimpleFunctionConsumer(
@@ -1,5 +1,5 @@
FILE: inBrackets.kt FILE: inBrackets.kt
public final fun test(e: R|kotlin/Int.() -> kotlin/String|): R|kotlin/Unit| { public final fun test(e: R|kotlin/Int.() -> kotlin/String|): R|kotlin/Unit| {
lval s: R|kotlin/String| = Int(3).R|<local>/e|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/String|>|(Int(3)) lval s: R|kotlin/String| = R|<local>/e|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/String|>|(Int(3))
lval ss: R|kotlin/String| = Int(3).R|<local>/e|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/String|>|(Int(3)) lval ss: R|kotlin/String| = R|<local>/e|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/String|>|(Int(3))
} }
@@ -15,10 +15,10 @@ FILE: propertyWithExtensionType.kt
when () { when () {
!=(R|<local>/a|.R|/A.x|, Null(null)) -> { !=(R|<local>/a|.R|/A.x|, Null(null)) -> {
lval b: R|kotlin/String.() -> kotlin/Unit| = R|<local>/a|.R|/A.x| lval b: R|kotlin/String.() -> kotlin/Unit| = R|<local>/a|.R|/A.x|
String().R|<local>/b|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(String()) R|<local>/b|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(String())
} }
} }
lval c: R|kotlin/String.() -> kotlin/Int| = R|<local>/a|.R|/A.y| lval c: R|kotlin/String.() -> kotlin/Int| = R|<local>/a|.R|/A.y|
lval d: R|kotlin/Int| = String().R|<local>/c|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Int|>|(String()) lval d: R|kotlin/Int| = R|<local>/c|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Int|>|(String())
} }
@@ -4,10 +4,10 @@ FILE: lambdaWithReceiver.kt
} }
public final fun <T> myWith(receiver: R|T|, block: R|T.() -> kotlin/Unit|): R|kotlin/Unit| { public final fun <T> myWith(receiver: R|T|, block: R|T.() -> kotlin/Unit|): R|kotlin/Unit| {
R|<local>/receiver|.R|<local>/block|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(R|<local>/receiver|) R|<local>/block|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(R|<local>/receiver|)
} }
public final fun <T> R|T|.myApply(block: R|T.() -> kotlin/Unit|): R|kotlin/Unit| { public final fun <T> R|T|.myApply(block: R|T.() -> kotlin/Unit|): R|kotlin/Unit| {
this@R|/myApply|.R|<local>/block|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(this@R|/myApply|) R|<local>/block|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(this@R|/myApply|)
} }
public final fun withA(block: R|A.() -> kotlin/Unit|): R|kotlin/Unit| { public final fun withA(block: R|A.() -> kotlin/Unit|): R|kotlin/Unit| {
} }
+1 -1
View File
@@ -5,7 +5,7 @@ FILE: functionTypes.kt
public final fun <T, R> R|kotlin/collections/List<T>|.simpleMap(f: R|(T) -> R|): R|R| { public final fun <T, R> R|kotlin/collections/List<T>|.simpleMap(f: R|(T) -> R|): R|R| {
} }
public final fun <T> simpleWith(t: R|T|, f: R|T.() -> kotlin/Unit|): R|kotlin/Unit| { public final fun <T> simpleWith(t: R|T|, f: R|T.() -> kotlin/Unit|): R|kotlin/Unit| {
^simpleWith R|<local>/t|.R|<local>/f|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(R|<local>/t|) ^simpleWith R|<local>/f|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(R|<local>/t|)
} }
public abstract interface KMutableProperty1<T, R> : R|KProperty1<T, R>|, R|KMutableProperty<R>| { public abstract interface KMutableProperty1<T, R> : R|KProperty1<T, R>|, R|KMutableProperty<R>| {
} }
@@ -2,7 +2,7 @@ FILE: invokeOfLambdaWithReceiver.kt
public abstract interface A : R|kotlin/Any| { public abstract interface A : R|kotlin/Any| {
} }
public final fun test(a: R|A|, block: R|A.() -> kotlin/Int|): R|kotlin/Unit| { public final fun test(a: R|A|, block: R|A.() -> kotlin/Int|): R|kotlin/Unit| {
R|<local>/a|.R|<local>/block|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Int|>|(R|<local>/a|) R|<local>/block|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Int|>|(R|<local>/a|)
} }
public abstract interface B : R|kotlin/Any| { public abstract interface B : R|kotlin/Any| {
} }