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:
@@ -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
|
||||||
|
|||||||
+15
-13
@@ -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)
|
||||||
|
|||||||
-2
@@ -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))
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -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
@@ -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>| {
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-3
@@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+9
-7
@@ -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)
|
||||||
|
|||||||
+17
-17
@@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+5
-5
@@ -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>'
|
||||||
|
|||||||
Reference in New Issue
Block a user