FIR resolve: introduce builtInExtensionFunctionReceiverValue

This commit allows us to distinguish extension lambda receivers
from simple extension receivers thus fixing some resolve problems.
This commit is contained in:
Mikhail Glukhikh
2019-12-26 13:38:04 +03:00
parent de50f8aef3
commit 0c88ecdc56
20 changed files with 144 additions and 101 deletions
@@ -308,12 +308,7 @@ class FirCallResolver(
val className = symbol.classId.shortClassName val className = symbol.classId.shortClassName
scope.processFunctionsByName(className) { scope.processFunctionsByName(className) {
if (it is FirConstructorSymbol) { if (it is FirConstructorSymbol) {
candidates += candidateFactory.createCandidate( candidates += candidateFactory.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER)
it,
dispatchReceiverValue = null,
implicitExtensionReceiverValue = null,
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
)
} }
ProcessorAction.NEXT ProcessorAction.NEXT
} }
@@ -45,6 +45,13 @@ class CallInfo(
val typeProvider: (FirExpression) -> FirTypeRef? val typeProvider: (FirExpression) -> FirTypeRef?
) { ) {
val argumentCount get() = arguments.size val argumentCount get() = arguments.size
fun withReceiverAsArgument(receiverExpression: FirExpression): CallInfo =
CallInfo(
callKind, explicitReceiver,
listOf(receiverExpression) + arguments,
isSafeCall, typeArguments, session, containingFile, implicitReceiverStack, expectedType, outerCSBuilder, lhs, typeProvider
)
} }
enum class CandidateApplicability { enum class CandidateApplicability {
@@ -30,15 +30,18 @@ class CandidateFactory(
fun createCandidate( fun createCandidate(
symbol: AbstractFirBasedSymbol<*>, symbol: AbstractFirBasedSymbol<*>,
dispatchReceiverValue: ClassDispatchReceiverValue?, explicitReceiverKind: ExplicitReceiverKind,
implicitExtensionReceiverValue: ImplicitReceiverValue<*>?, dispatchReceiverValue: ClassDispatchReceiverValue? = null,
explicitReceiverKind: ExplicitReceiverKind implicitExtensionReceiverValue: ImplicitReceiverValue<*>? = null,
builtInExtensionFunctionReceiverValue: ReceiverValue? = null
): Candidate { ): Candidate {
val candidate = Candidate( return Candidate(
symbol, dispatchReceiverValue, implicitExtensionReceiverValue, symbol, dispatchReceiverValue, implicitExtensionReceiverValue,
explicitReceiverKind, bodyResolveComponents, baseSystem, callInfo explicitReceiverKind, bodyResolveComponents, baseSystem,
builtInExtensionFunctionReceiverValue?.receiverExpression?.let {
callInfo.withReceiverAsArgument(it)
} ?: callInfo
) )
return candidate
} }
} }
@@ -8,9 +8,7 @@ package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
@@ -139,23 +137,6 @@ internal object MapArguments : ResolutionStage() {
override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) { override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
val symbol = candidate.symbol as? FirFunctionSymbol<*> ?: return sink.reportApplicability(CandidateApplicability.HIDDEN) val symbol = candidate.symbol as? FirFunctionSymbol<*> ?: return sink.reportApplicability(CandidateApplicability.HIDDEN)
val function = symbol.fir val function = symbol.fir
if (candidate.dispatchReceiverValue?.type?.isBuiltinFunctionalType == true) {
// We don't know is it extension function or not due to lack of annotations
// So we have to check both variants, with receiver and without it
// TODO: remove this double-check after KT-30066
val lambdaExtensionReceiver =
(callInfo.explicitReceiver as? FirQualifiedAccess)?.extensionReceiver?.takeIf { it !is FirNoReceiverExpression }
?: (candidate.implicitExtensionReceiverValue as? ImplicitReceiverValue)?.receiverExpression
val processorWithReceiver = FirCallArgumentsProcessor(
function,
listOfNotNull(lambdaExtensionReceiver) + callInfo.arguments
)
val mappingResult = processorWithReceiver.process()
candidate.argumentMapping = mappingResult.argumentMapping
if (mappingResult.isSuccess) {
return
}
}
val processor = FirCallArgumentsProcessor(function, callInfo.arguments) val processor = FirCallArgumentsProcessor(function, callInfo.arguments)
val mappingResult = processor.process() val mappingResult = processor.process()
candidate.argumentMapping = mappingResult.argumentMapping candidate.argumentMapping = mappingResult.argumentMapping
@@ -66,17 +66,13 @@ class QualifiedReceiverTowerDataConsumer<T : AbstractFirBasedSymbol<*>>(
override fun consumeCandidate( override fun consumeCandidate(
symbol: T, symbol: T,
dispatchReceiverValue: ClassDispatchReceiverValue?, dispatchReceiverValue: ClassDispatchReceiverValue?,
implicitExtensionReceiverValue: ImplicitReceiverValue<*>? implicitExtensionReceiverValue: ImplicitReceiverValue<*>?,
builtInExtensionFunctionReceiverValue: ReceiverValue?
): ProcessorAction { ): ProcessorAction {
assert(dispatchReceiverValue == null) assert(dispatchReceiverValue == null)
resultCollector.consumeCandidate( resultCollector.consumeCandidate(
group, group,
candidateFactory.createCandidate( candidateFactory.createCandidate(symbol, explicitReceiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER)
symbol,
dispatchReceiverValue = null,
implicitExtensionReceiverValue = null,
explicitReceiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
)
) )
return ProcessorAction.NEXT return ProcessorAction.NEXT
} }
@@ -203,15 +199,17 @@ class ExplicitReceiverTowerDataConsumer<T : AbstractFirBasedSymbol<*>>(
override fun consumeCandidate( override fun consumeCandidate(
symbol: T, symbol: T,
dispatchReceiverValue: ClassDispatchReceiverValue?, dispatchReceiverValue: ClassDispatchReceiverValue?,
implicitExtensionReceiverValue: ImplicitReceiverValue<*>? implicitExtensionReceiverValue: ImplicitReceiverValue<*>?,
builtInExtensionFunctionReceiverValue: ReceiverValue?
): ProcessorAction { ): ProcessorAction {
resultCollector.consumeCandidate( resultCollector.consumeCandidate(
group, group,
candidateFactory.createCandidate( candidateFactory.createCandidate(
symbol, symbol,
ExplicitReceiverKind.DISPATCH_RECEIVER,
dispatchReceiverValue, dispatchReceiverValue,
implicitExtensionReceiverValue, implicitExtensionReceiverValue,
ExplicitReceiverKind.DISPATCH_RECEIVER builtInExtensionFunctionReceiverValue
) )
) )
return ProcessorAction.NEXT return ProcessorAction.NEXT
@@ -222,7 +220,8 @@ class ExplicitReceiverTowerDataConsumer<T : AbstractFirBasedSymbol<*>>(
override fun consumeCandidate( override fun consumeCandidate(
symbol: T, symbol: T,
dispatchReceiverValue: ClassDispatchReceiverValue?, dispatchReceiverValue: ClassDispatchReceiverValue?,
implicitExtensionReceiverValue: ImplicitReceiverValue<*>? implicitExtensionReceiverValue: ImplicitReceiverValue<*>?,
builtInExtensionFunctionReceiverValue: ReceiverValue?
): ProcessorAction { ): ProcessorAction {
if (symbol is FirNamedFunctionSymbol && symbol.callableId.packageName.startsWith(defaultPackage)) { if (symbol is FirNamedFunctionSymbol && symbol.callableId.packageName.startsWith(defaultPackage)) {
val explicitReceiverType = explicitReceiver.type val explicitReceiverType = explicitReceiver.type
@@ -247,9 +246,10 @@ class ExplicitReceiverTowerDataConsumer<T : AbstractFirBasedSymbol<*>>(
} }
val candidate = candidateFactory.createCandidate( val candidate = candidateFactory.createCandidate(
symbol, symbol,
ExplicitReceiverKind.EXTENSION_RECEIVER,
dispatchReceiverValue, dispatchReceiverValue,
implicitExtensionReceiverValue, implicitExtensionReceiverValue,
ExplicitReceiverKind.EXTENSION_RECEIVER builtInExtensionFunctionReceiverValue
) )
resultCollector.consumeCandidate( resultCollector.consumeCandidate(
@@ -292,15 +292,17 @@ class NoExplicitReceiverTowerDataConsumer<T : AbstractFirBasedSymbol<*>>(
override fun consumeCandidate( override fun consumeCandidate(
symbol: T, symbol: T,
dispatchReceiverValue: ClassDispatchReceiverValue?, dispatchReceiverValue: ClassDispatchReceiverValue?,
implicitExtensionReceiverValue: ImplicitReceiverValue<*>? implicitExtensionReceiverValue: ImplicitReceiverValue<*>?,
builtInExtensionFunctionReceiverValue: ReceiverValue?
): ProcessorAction { ): ProcessorAction {
resultCollector.consumeCandidate( resultCollector.consumeCandidate(
group, group,
candidateFactory.createCandidate( candidateFactory.createCandidate(
symbol, symbol,
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
dispatchReceiverValue, dispatchReceiverValue,
implicitExtensionReceiverValue, implicitExtensionReceiverValue,
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER builtInExtensionFunctionReceiverValue
) )
) )
return ProcessorAction.NEXT return ProcessorAction.NEXT
@@ -10,7 +10,9 @@ import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirImportImpl import org.jetbrains.kotlin.fir.declarations.impl.FirImportImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedImportImpl import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedImportImpl
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
@@ -46,7 +48,8 @@ interface TowerScopeLevel {
fun consumeCandidate( fun consumeCandidate(
symbol: T, symbol: T,
dispatchReceiverValue: ClassDispatchReceiverValue?, dispatchReceiverValue: ClassDispatchReceiverValue?,
implicitExtensionReceiverValue: ImplicitReceiverValue<*>? implicitExtensionReceiverValue: ImplicitReceiverValue<*>?,
builtInExtensionFunctionReceiverValue: ReceiverValue?
): ProcessorAction ): ProcessorAction
} }
@@ -100,6 +103,7 @@ class MemberScopeTowerLevel(
private fun <T : AbstractFirBasedSymbol<*>> processMembers( private fun <T : AbstractFirBasedSymbol<*>> processMembers(
output: TowerScopeLevel.TowerScopeLevelProcessor<T>, output: TowerScopeLevel.TowerScopeLevelProcessor<T>,
explicitExtensionReceiver: ExpressionReceiverValue?, explicitExtensionReceiver: ExpressionReceiverValue?,
isInvoke: Boolean,
processScopeMembers: FirScope.(processor: (T) -> ProcessorAction) -> ProcessorAction processScopeMembers: FirScope.(processor: (T) -> ProcessorAction) -> ProcessorAction
): ProcessorAction { ): ProcessorAction {
if (implicitExtensionReceiver != null && explicitExtensionReceiver != null) return ProcessorAction.NEXT if (implicitExtensionReceiver != null && explicitExtensionReceiver != null) return ProcessorAction.NEXT
@@ -109,9 +113,47 @@ class MemberScopeTowerLevel(
if (candidate is FirCallableSymbol<*> && (invokeOnly || candidate.hasConsistentExtensionReceiver(extensionReceiver))) { if (candidate is FirCallableSymbol<*> && (invokeOnly || candidate.hasConsistentExtensionReceiver(extensionReceiver))) {
// NB: we do not check dispatchReceiverValue != null here, // NB: we do not check dispatchReceiverValue != null here,
// because of objects & constructors (see comments in dispatchReceiverValue() implementation) // because of objects & constructors (see comments in dispatchReceiverValue() implementation)
output.consumeCandidate(candidate, candidate.dispatchReceiverValue(), implicitExtensionReceiver) val dispatchReceiverValue = candidate.dispatchReceiverValue()
if (invokeOnly) {
if (output.consumeCandidate(
candidate, dispatchReceiverValue,
implicitExtensionReceiverValue = implicitExtensionReceiver,
builtInExtensionFunctionReceiverValue = null
).stop()
) {
ProcessorAction.STOP
} else {
output.consumeCandidate(
candidate, dispatchReceiverValue,
implicitExtensionReceiverValue = null,
builtInExtensionFunctionReceiverValue = implicitExtensionReceiver
)
}
} else {
val builtInFunctionReceiverExpression =
if (!isInvoke || dispatchReceiver !is ExpressionReceiverValue) null
else (dispatchReceiver.explicitReceiverExpression as? FirQualifiedAccess)?.extensionReceiver
if (dispatchReceiver !is ExpressionReceiverValue ||
builtInFunctionReceiverExpression == null ||
builtInFunctionReceiverExpression is FirNoReceiverExpression
) {
output.consumeCandidate(candidate, dispatchReceiverValue, implicitExtensionReceiver, null)
} else {
if (output.consumeCandidate(candidate, dispatchReceiverValue, implicitExtensionReceiver, null).stop()) {
ProcessorAction.STOP
} else {
output.consumeCandidate(
candidate, dispatchReceiverValue,
implicitExtensionReceiverValue = null,
builtInExtensionFunctionReceiverValue = ExpressionReceiverValue(
builtInFunctionReceiverExpression, dispatchReceiver.typeProvider
)
)
}
}
}
} else if (candidate is FirClassLikeSymbol<*>) { } else if (candidate is FirClassLikeSymbol<*>) {
output.consumeCandidate(candidate, null, implicitExtensionReceiver) output.consumeCandidate(candidate, null, implicitExtensionReceiver, null)
} else { } else {
ProcessorAction.NEXT ProcessorAction.NEXT
} }
@@ -119,7 +161,7 @@ class MemberScopeTowerLevel(
) return ProcessorAction.STOP ) return ProcessorAction.STOP
val withSynthetic = FirSyntheticPropertiesScope(session, scope) val withSynthetic = FirSyntheticPropertiesScope(session, scope)
return withSynthetic.processScopeMembers { symbol -> return withSynthetic.processScopeMembers { symbol ->
output.consumeCandidate(symbol, symbol.dispatchReceiverValue(), implicitExtensionReceiver) output.consumeCandidate(symbol, symbol.dispatchReceiverValue(), implicitExtensionReceiver, null)
} }
} }
@@ -129,18 +171,19 @@ class MemberScopeTowerLevel(
explicitReceiver: ExpressionReceiverValue?, explicitReceiver: ExpressionReceiverValue?,
processor: TowerScopeLevel.TowerScopeLevelProcessor<T> processor: TowerScopeLevel.TowerScopeLevelProcessor<T>
): ProcessorAction { ): ProcessorAction {
if (invokeOnly && (token != TowerScopeLevel.Token.Functions || name != OperatorNameConventions.INVOKE)) { val isInvoke = name == OperatorNameConventions.INVOKE && token == TowerScopeLevel.Token.Functions
if (invokeOnly && !isInvoke) {
return ProcessorAction.NEXT return ProcessorAction.NEXT
} }
val explicitExtensionReceiver = if (dispatchReceiver == explicitReceiver) null else explicitReceiver val explicitExtensionReceiver = if (dispatchReceiver == explicitReceiver) null else explicitReceiver
return when (token) { return when (token) {
TowerScopeLevel.Token.Properties -> processMembers(processor, explicitExtensionReceiver) { symbol -> TowerScopeLevel.Token.Properties -> processMembers(processor, explicitExtensionReceiver, isInvoke) { symbol ->
this.processPropertiesByName(name, symbol.cast()) this.processPropertiesByName(name, symbol.cast())
} }
TowerScopeLevel.Token.Functions -> processMembers(processor, explicitExtensionReceiver) { symbol -> TowerScopeLevel.Token.Functions -> processMembers(processor, explicitExtensionReceiver, isInvoke) { symbol ->
this.processFunctionsAndConstructorsByName(name, session, bodyResolveComponents, symbol.cast()) this.processFunctionsAndConstructorsByName(name, session, bodyResolveComponents, symbol.cast())
} }
TowerScopeLevel.Token.Objects -> processMembers(processor, explicitExtensionReceiver) { symbol -> TowerScopeLevel.Token.Objects -> processMembers(processor, explicitExtensionReceiver, isInvoke) { symbol ->
this.processClassifiersByName(name, symbol.cast()) this.processClassifiersByName(name, symbol.cast())
} }
} }
@@ -189,7 +232,8 @@ class ScopeTowerLevel(
} }
processor.consumeCandidate( processor.consumeCandidate(
candidate as T, dispatchReceiverValue = dispatchReceiverValue, candidate as T, dispatchReceiverValue = dispatchReceiverValue,
implicitExtensionReceiverValue = implicitExtensionReceiver implicitExtensionReceiverValue = implicitExtensionReceiver,
builtInExtensionFunctionReceiverValue = null
) )
} else { } else {
ProcessorAction.NEXT ProcessorAction.NEXT
@@ -203,7 +247,8 @@ class ScopeTowerLevel(
if (candidate.hasConsistentReceivers(extensionReceiver)) { if (candidate.hasConsistentReceivers(extensionReceiver)) {
processor.consumeCandidate( processor.consumeCandidate(
candidate as T, dispatchReceiverValue = candidate.dispatchReceiverValue(), candidate as T, dispatchReceiverValue = candidate.dispatchReceiverValue(),
implicitExtensionReceiverValue = implicitExtensionReceiver implicitExtensionReceiverValue = implicitExtensionReceiver,
builtInExtensionFunctionReceiverValue = null
) )
} else { } else {
ProcessorAction.NEXT ProcessorAction.NEXT
@@ -212,7 +257,8 @@ class ScopeTowerLevel(
TowerScopeLevel.Token.Objects -> scope.processClassifiersByName(name) { TowerScopeLevel.Token.Objects -> scope.processClassifiersByName(name) {
processor.consumeCandidate( processor.consumeCandidate(
it as T, dispatchReceiverValue = null, it as T, dispatchReceiverValue = null,
implicitExtensionReceiverValue = null implicitExtensionReceiverValue = null,
builtInExtensionFunctionReceiverValue = null
) )
} }
} }
@@ -259,7 +305,7 @@ class QualifiedReceiverTowerLevel(
fir is FirConstructor && !fir.isInner fir is FirConstructor && !fir.isInner
) { ) {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
processor.consumeCandidate(it as T, null, null) processor.consumeCandidate(it as T, null, null, null)
} else { } else {
ProcessorAction.NEXT ProcessorAction.NEXT
} }
@@ -268,7 +314,7 @@ class QualifiedReceiverTowerLevel(
return when (token) { return when (token) {
TowerScopeLevel.Token.Objects -> scope.processClassifiersByName(name) { TowerScopeLevel.Token.Objects -> scope.processClassifiersByName(name) {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
processor.consumeCandidate(it as T, null, null) processor.consumeCandidate(it as T, null, null, null)
} }
TowerScopeLevel.Token.Functions -> { TowerScopeLevel.Token.Functions -> {
scope.processFunctionsAndConstructorsByName(name, session, bodyResolveComponents, processorForCallables) scope.processFunctionsAndConstructorsByName(name, session, bodyResolveComponents, processorForCallables)
@@ -134,8 +134,6 @@ class FirSyntheticCallGenerator(
private fun generateCandidate(callInfo: CallInfo, function: FirSimpleFunctionImpl): Candidate = private fun generateCandidate(callInfo: CallInfo, function: FirSimpleFunctionImpl): Candidate =
CandidateFactory(components, callInfo).createCandidate( CandidateFactory(components, callInfo).createCandidate(
symbol = function.symbol, symbol = function.symbol,
dispatchReceiverValue = null,
implicitExtensionReceiverValue = null,
explicitReceiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER explicitReceiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
) )
@@ -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|>|() lval s: R|kotlin/String| = Int(3).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|>|() lval ss: R|kotlin/String| = Int(3).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|>|() lval d: R|kotlin/Int| = String().R|<local>/c|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Int|>|(String())
} }
@@ -12,6 +12,10 @@ class Foo {
val Buz.foobar: Bar get() = Bar() val Buz.foobar: Bar get() = Bar()
fun FooBar.chk(buz: Buz) { fun FooBar.chk(buz: Buz) {
// local/buz is extension receiver of foobar
// this@Foo is dispatch receiver of foobar
// Foo/foobar is dispatch receiver of invoke
// this@chk is extension receiver of invoke
buz.foobar() buz.foobar()
} }
} }
@@ -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|>|() ^simpleWith R|<local>/t|.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>| {
} }
@@ -4,12 +4,14 @@ fun test(a: A, block: A.() -> Int) {
a.block() a.block()
} }
fun A.otherTest(block: A.() -> Int) { interface B
fun B.otherTest(block: B.() -> Int) {
block() block()
} }
class B { class C {
fun anotherTest(block: B.() -> Int) { fun anotherTest(block: C.() -> Int) {
block() block()
} }
} }
@@ -2,18 +2,20 @@ 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 final fun R|A|.otherTest(block: R|A.() -> kotlin/Int|): R|kotlin/Unit| { public abstract interface B : R|kotlin/Any| {
(R|<local>/block|, this@R|/otherTest|).R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Int|>|()
} }
public final class B : R|kotlin/Any| { public final fun R|B|.otherTest(block: R|B.() -> kotlin/Int|): R|kotlin/Unit| {
public constructor(): R|B| { R|<local>/block|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Int|>|(this@R|/otherTest|)
}
public final class C : R|kotlin/Any| {
public constructor(): R|C| {
super<R|kotlin/Any|>() super<R|kotlin/Any|>()
} }
public final fun anotherTest(block: R|B.() -> kotlin/Int|): R|kotlin/Unit| { public final fun anotherTest(block: R|C.() -> kotlin/Int|): R|kotlin/Unit| {
(R|<local>/block|, this@R|/B|).R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Int|>|() R|<local>/block|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Int|>|(this@R|/C|)
} }
} }
@@ -26,7 +26,7 @@ fun <T> fooT2() : (t : T) -> T {
fun main(args : Array<String>) { fun main(args : Array<String>) {
args.foo()() args.foo()()
<!INAPPLICABLE_CANDIDATE!>args.foo1()()<!> <!INAPPLICABLE_CANDIDATE!>args.foo1()()<!>
<!UNRESOLVED_REFERENCE!>a<!>.foo1()() <!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>a<!>.foo1()()
<!UNRESOLVED_REFERENCE!>a<!>.foo1()(<!UNRESOLVED_REFERENCE!>a<!>) <!UNRESOLVED_REFERENCE!>a<!>.foo1()(<!UNRESOLVED_REFERENCE!>a<!>)
args.foo1()(1) args.foo1()(1)
@@ -35,37 +35,37 @@ fun test() {
foo { foo {
bar { bar {
baz { baz {
<!INAPPLICABLE_CANDIDATE!>y<!>() y()
<!UNRESOLVED_REFERENCE!>x<!>() <!UNRESOLVED_REFERENCE!>x<!>()
with(D()) { with(D()) {
<!INAPPLICABLE_CANDIDATE!>x<!>() x()
} }
foo1 { foo1 {
<!INAPPLICABLE_CANDIDATE!>x<!>() x()
<!INAPPLICABLE_CANDIDATE!>y<!>() y()
with(A()) { with(A()) {
<!INAPPLICABLE_CANDIDATE!>x<!>() x()
<!INAPPLICABLE_CANDIDATE!>y<!>() y()
} }
with(D()) { with(D()) {
<!INAPPLICABLE_CANDIDATE!>x<!>() x()
} }
A().<!UNRESOLVED_REFERENCE!>x<!>() A().<!UNRESOLVED_REFERENCE!>x<!>()
} }
foo2 { foo2 {
<!INAPPLICABLE_CANDIDATE!>x<!>() x()
<!INAPPLICABLE_CANDIDATE!>y<!>() y()
} }
foo3 { foo3 {
<!INAPPLICABLE_CANDIDATE!>x<!>() x()
<!INAPPLICABLE_CANDIDATE!>y<!>() y()
} }
} }
} }
@@ -75,8 +75,8 @@ fun test() {
foo { foo {
baz { baz {
bar { bar {
<!INAPPLICABLE_CANDIDATE!>x<!>() x()
<!INAPPLICABLE_CANDIDATE!>y<!>() y()
} }
} }
} }
@@ -86,8 +86,8 @@ fun test() {
foo { foo {
baz { baz {
bar { bar {
<!INAPPLICABLE_CANDIDATE!>x<!>() x()
<!INAPPLICABLE_CANDIDATE!>y<!>() y()
} }
} }
} }
@@ -97,8 +97,8 @@ fun test() {
foo { foo {
baz { baz {
bar { bar {
<!INAPPLICABLE_CANDIDATE!>x<!>() x()
<!INAPPLICABLE_CANDIDATE!>y<!>() y()
} }
} }
} }
@@ -24,10 +24,10 @@ fun test(a: A, b: B) {
} }
with(b) { with(b) {
a.<!INAPPLICABLE_CANDIDATE!>foo<!>() a.foo()
a.(<!INAPPLICABLE_CANDIDATE!>foo<!>)() a.(foo)()
<!INAPPLICABLE_CANDIDATE!>(a.foo)()<!> (a.foo)()
(a.foo)(this) (a.foo)(this)
a.foo(this) a.foo(this)
@@ -35,8 +35,8 @@ fun test(a: A, b: B) {
with(a) { with(a) {
with(b) { with(b) {
<!INAPPLICABLE_CANDIDATE!>foo<!>() foo()
(<!INAPPLICABLE_CANDIDATE!>foo<!>)() (foo)()
} }
} }
} }
@@ -14,3 +14,4 @@ FILE fqName:<root> fileName:/extFunInvokeAsFun.kt
RETURN type=kotlin.Nothing from='public final fun with2 (receiver: kotlin.Any?, block: kotlin.Function1<kotlin.Any?, kotlin.Unit>): kotlin.Unit declared in <root>' RETURN type=kotlin.Nothing from='public final fun with2 (receiver: kotlin.Any?, block: kotlin.Function1<kotlin.Any?, kotlin.Unit>): kotlin.Unit declared in <root>'
CALL 'public abstract fun invoke (p1: kotlin.Any?): kotlin.Unit [operator] declared in kotlin.Function1' type=kotlin.Unit origin=null CALL 'public abstract fun invoke (p1: kotlin.Any?): kotlin.Unit [operator] declared in kotlin.Function1' type=kotlin.Unit origin=null
$this: GET_VAR 'block: kotlin.Function1<kotlin.Any?, kotlin.Unit> declared in <root>.with2' type=kotlin.Function1<kotlin.Any?, kotlin.Unit> origin=null $this: GET_VAR 'block: kotlin.Function1<kotlin.Any?, kotlin.Unit> declared in <root>.with2' type=kotlin.Function1<kotlin.Any?, kotlin.Unit> origin=null
p1: GET_VAR 'receiver: kotlin.Any? declared in <root>.with2' type=kotlin.Any? origin=null
@@ -6,5 +6,6 @@ FILE fqName:<root> fileName:/extFunSafeInvoke.kt
RETURN type=kotlin.Nothing from='public final fun test (receiver: kotlin.Any?, fn: kotlin.Function3<kotlin.Any, kotlin.Int, kotlin.String, kotlin.Unit>): kotlin.Unit? declared in <root>' RETURN type=kotlin.Nothing from='public final fun test (receiver: kotlin.Any?, fn: kotlin.Function3<kotlin.Any, kotlin.Int, kotlin.String, kotlin.Unit>): kotlin.Unit? declared in <root>'
CALL 'public abstract fun invoke (p1: kotlin.Any, p2: kotlin.Int, p3: kotlin.String): kotlin.Unit [operator] declared in kotlin.Function3' type=kotlin.Unit? origin=null CALL 'public abstract fun invoke (p1: kotlin.Any, p2: kotlin.Int, p3: kotlin.String): kotlin.Unit [operator] declared in kotlin.Function3' type=kotlin.Unit? origin=null
$this: GET_VAR 'fn: kotlin.Function3<kotlin.Any, kotlin.Int, kotlin.String, kotlin.Unit> declared in <root>.test' type=kotlin.Function3<kotlin.Any, kotlin.Int, kotlin.String, kotlin.Unit> origin=null $this: GET_VAR 'fn: kotlin.Function3<kotlin.Any, kotlin.Int, kotlin.String, kotlin.Unit> declared in <root>.test' type=kotlin.Function3<kotlin.Any, kotlin.Int, kotlin.String, kotlin.Unit> origin=null
p1: CONST Int type=kotlin.Int value=42 p1: GET_VAR 'receiver: kotlin.Any? declared in <root>.test' type=kotlin.Any? origin=null
p2: CONST String type=kotlin.String value="Hello" p2: CONST Int type=kotlin.Int value=42
p3: CONST String type=kotlin.String value="Hello"
@@ -19,6 +19,7 @@ FILE fqName:<root> fileName:/variableAsFunctionCall.kt
RETURN type=kotlin.Nothing from='public final fun test2 (f: kotlin.Function1<kotlin.String, kotlin.Unit>): kotlin.Unit declared in <root>' RETURN type=kotlin.Nothing from='public final fun test2 (f: kotlin.Function1<kotlin.String, kotlin.Unit>): kotlin.Unit declared in <root>'
CALL 'public abstract fun invoke (p1: kotlin.String): kotlin.Unit [operator] declared in kotlin.Function1' type=kotlin.Unit origin=null CALL 'public abstract fun invoke (p1: kotlin.String): kotlin.Unit [operator] declared in kotlin.Function1' type=kotlin.Unit origin=null
$this: GET_VAR 'f: kotlin.Function1<kotlin.String, kotlin.Unit> declared in <root>.test2' type=kotlin.Function1<kotlin.String, kotlin.Unit> origin=null $this: GET_VAR 'f: kotlin.Function1<kotlin.String, kotlin.Unit> declared in <root>.test2' type=kotlin.Function1<kotlin.String, kotlin.Unit> origin=null
p1: CONST String type=kotlin.String value="hello"
FUN name:test3 visibility:public modality:FINAL <> () returnType:kotlin.String FUN name:test3 visibility:public modality:FINAL <> () returnType:kotlin.String
BLOCK_BODY BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test3 (): kotlin.String declared in <root>' RETURN type=kotlin.Nothing from='public final fun test3 (): kotlin.String declared in <root>'