[FIR] Add smartcast info to argument of invoke of function with receiver

This commit is contained in:
Dmitriy Novozhilov
2020-02-13 15:57:42 +03:00
parent 4fbed9b363
commit 50ac8eb95b
3 changed files with 19 additions and 4 deletions
@@ -6,9 +6,12 @@
package org.jetbrains.kotlin.fir.resolve.calls package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.buildExpressionWithSmartcast
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype
import org.jetbrains.kotlin.fir.returnExpressions import org.jetbrains.kotlin.fir.returnExpressions
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
@@ -46,10 +49,23 @@ class CandidateFactory private constructor(
implicitExtensionReceiverValue: ImplicitReceiverValue<*>? = null, implicitExtensionReceiverValue: ImplicitReceiverValue<*>? = null,
builtInExtensionFunctionReceiverValue: ReceiverValue? = null builtInExtensionFunctionReceiverValue: ReceiverValue? = null
): Candidate { ): Candidate {
val receiverExpression = builtInExtensionFunctionReceiverValue?.let {
val receiverExpression = builtInExtensionFunctionReceiverValue.receiverExpression
if (receiverExpression is FirQualifiedAccessExpression &&
it.type != builtInExtensionFunctionReceiverValue.receiverExpression.typeRef.coneTypeUnsafe()) {
buildExpressionWithSmartcast {
originalExpression = receiverExpression
typeRef = receiverExpression.typeRef.resolvedTypeFromPrototype(it.type)
typesFromSmartCast = listOf(it.type)
}
} else {
receiverExpression
}
}
return Candidate( return Candidate(
symbol, dispatchReceiverValue, implicitExtensionReceiverValue, symbol, dispatchReceiverValue, implicitExtensionReceiverValue,
explicitReceiverKind, bodyResolveComponents, baseSystem, explicitReceiverKind, bodyResolveComponents, baseSystem,
builtInExtensionFunctionReceiverValue?.receiverExpression?.let { receiverExpression?.let {
callInfo.withReceiverAsArgument(it) callInfo.withReceiverAsArgument(it)
} ?: callInfo } ?: callInfo
) )
@@ -1,10 +1,9 @@
fun Any.withInvoke(f: String.() -> Unit) { fun Any.withInvoke(f: String.() -> Unit) {
if (this is String) { if (this is String) {
<!INAPPLICABLE_CANDIDATE!>f<!>() // Should be OK f() // Should be OK
} }
} }
fun String.withInvoke(f: String.() -> Unit) { fun String.withInvoke(f: String.() -> Unit) {
f() f()
} }
@@ -2,7 +2,7 @@ FILE: invoke.kt
public final fun R|kotlin/Any|.withInvoke(f: R|kotlin/String.() -> kotlin/Unit|): R|kotlin/Unit| { public final fun R|kotlin/Any|.withInvoke(f: R|kotlin/String.() -> kotlin/Unit|): R|kotlin/Unit| {
when () { when () {
(this@R|/withInvoke| is R|kotlin/String|) -> { (this@R|/withInvoke| is R|kotlin/String|) -> {
<Inapplicable(INAPPLICABLE): [kotlin/Function1.invoke]>#() R|<local>/f|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(this@R|/withInvoke|)
} }
} }