FIR: partially implement invoke resolution
This commit is contained in:
@@ -12,6 +12,8 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirImportImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedImportImpl
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirQualifiedAccessExpressionImpl
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReferenceImpl
|
||||
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.constructClassType
|
||||
@@ -96,7 +98,8 @@ class Candidate(
|
||||
val implicitExtensionReceiverValue: ImplicitReceiverValue?,
|
||||
val explicitReceiverKind: ExplicitReceiverKind,
|
||||
private val inferenceComponents: InferenceComponents,
|
||||
private val baseSystem: ConstraintStorage
|
||||
private val baseSystem: ConstraintStorage,
|
||||
val callInfo: CallInfo
|
||||
) {
|
||||
val system by lazy {
|
||||
val system = inferenceComponents.createConstraintSystem()
|
||||
@@ -281,7 +284,8 @@ class ScopeTowerLevel(
|
||||
if (candidate.hasConsistentExtensionReceiver(extensionReceiver) && candidate.dispatchReceiverValue() == null) {
|
||||
processor.consumeCandidate(
|
||||
candidate as T, dispatchReceiverValue = null,
|
||||
implicitExtensionReceiverValue = implicitExtensionReceiver)
|
||||
implicitExtensionReceiverValue = implicitExtensionReceiver
|
||||
)
|
||||
} else {
|
||||
ProcessorAction.NEXT
|
||||
}
|
||||
@@ -342,15 +346,15 @@ class QualifiedReceiverTowerDataConsumer<T : ConeSymbol>(
|
||||
val name: Name,
|
||||
val token: TowerScopeLevel.Token<T>,
|
||||
val explicitReceiver: ExpressionReceiverValue,
|
||||
val candidateFactory: CandidateFactory
|
||||
val candidateFactory: CandidateFactory,
|
||||
val resultCollector: CandidateCollector
|
||||
) : TowerDataConsumer() {
|
||||
override fun consume(
|
||||
kind: TowerDataKind,
|
||||
towerScopeLevel: TowerScopeLevel,
|
||||
resultCollector: CandidateCollector,
|
||||
group: Int
|
||||
): ProcessorAction {
|
||||
if (checkSkip(group, resultCollector)) return ProcessorAction.NEXT
|
||||
if (skipGroup(group, resultCollector)) return ProcessorAction.NEXT
|
||||
if (kind != TowerDataKind.EMPTY) return ProcessorAction.NEXT
|
||||
|
||||
return QualifiedReceiverTowerLevel(session).processElementsByName(
|
||||
@@ -385,16 +389,16 @@ abstract class TowerDataConsumer {
|
||||
abstract fun consume(
|
||||
kind: TowerDataKind,
|
||||
towerScopeLevel: TowerScopeLevel,
|
||||
resultCollector: CandidateCollector,
|
||||
// resultCollector: CandidateCollector,
|
||||
group: Int
|
||||
): ProcessorAction
|
||||
|
||||
private var stopGroup = Int.MAX_VALUE
|
||||
fun checkSkip(group: Int, resultCollector: CandidateCollector): Boolean {
|
||||
fun skipGroup(group: Int, resultCollector: CandidateCollector): Boolean {
|
||||
if (resultCollector.isSuccess() && stopGroup == Int.MAX_VALUE) {
|
||||
stopGroup = group
|
||||
}
|
||||
return group > stopGroup
|
||||
} else if (group > stopGroup) return true
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -403,39 +407,94 @@ fun createVariableAndObjectConsumer(
|
||||
session: FirSession,
|
||||
name: Name,
|
||||
callInfo: CallInfo,
|
||||
inferenceComponents: InferenceComponents
|
||||
inferenceComponents: InferenceComponents,
|
||||
resultCollector: CandidateCollector
|
||||
): TowerDataConsumer {
|
||||
return PrioritizedTowerDataConsumer(
|
||||
resultCollector,
|
||||
createSimpleConsumer(
|
||||
session,
|
||||
name,
|
||||
TowerScopeLevel.Token.Properties,
|
||||
callInfo,
|
||||
inferenceComponents
|
||||
inferenceComponents,
|
||||
resultCollector
|
||||
),
|
||||
createSimpleConsumer(
|
||||
session,
|
||||
name,
|
||||
TowerScopeLevel.Token.Objects,
|
||||
callInfo,
|
||||
inferenceComponents
|
||||
inferenceComponents,
|
||||
resultCollector
|
||||
)
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
fun createFunctionConsumer(
|
||||
fun createSimpleFunctionConsumer(
|
||||
session: FirSession,
|
||||
name: Name,
|
||||
callInfo: CallInfo,
|
||||
inferenceComponents: InferenceComponents
|
||||
inferenceComponents: InferenceComponents,
|
||||
resultCollector: CandidateCollector
|
||||
): TowerDataConsumer {
|
||||
return createSimpleConsumer(
|
||||
session,
|
||||
name,
|
||||
TowerScopeLevel.Token.Functions,
|
||||
callInfo,
|
||||
inferenceComponents
|
||||
inferenceComponents,
|
||||
resultCollector
|
||||
)
|
||||
}
|
||||
|
||||
fun createFunctionConsumer(
|
||||
session: FirSession,
|
||||
name: Name,
|
||||
callInfo: CallInfo,
|
||||
inferenceComponents: InferenceComponents,
|
||||
resultCollector: CandidateCollector,
|
||||
callResolver: CallResolver
|
||||
): TowerDataConsumer {
|
||||
val varCallInfo = CallInfo(
|
||||
CallKind.VariableAccess,
|
||||
callInfo.explicitReceiver,
|
||||
emptyList(),
|
||||
callInfo.isSafeCall,
|
||||
callInfo.typeArguments,
|
||||
inferenceComponents.session,
|
||||
callInfo.containingFile,
|
||||
callInfo.container,
|
||||
callInfo.typeProvider
|
||||
)
|
||||
return PrioritizedTowerDataConsumer(
|
||||
resultCollector,
|
||||
createSimpleConsumer(
|
||||
session,
|
||||
name,
|
||||
TowerScopeLevel.Token.Functions,
|
||||
callInfo,
|
||||
inferenceComponents,
|
||||
resultCollector
|
||||
),
|
||||
MultiplexerTowerDataConsumer(resultCollector).apply {
|
||||
addConsumer(
|
||||
createSimpleConsumer(
|
||||
session,
|
||||
name,
|
||||
TowerScopeLevel.Token.Properties,
|
||||
varCallInfo,
|
||||
inferenceComponents,
|
||||
InvokeCandidateCollector(
|
||||
callResolver,
|
||||
invokeCallInfo = callInfo,
|
||||
components = inferenceComponents,
|
||||
multiplexer = this
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -445,7 +504,8 @@ fun createSimpleConsumer(
|
||||
name: Name,
|
||||
token: TowerScopeLevel.Token<*>,
|
||||
callInfo: CallInfo,
|
||||
inferenceComponents: InferenceComponents
|
||||
inferenceComponents: InferenceComponents,
|
||||
resultCollector: CandidateCollector
|
||||
): TowerDataConsumer {
|
||||
val factory = CandidateFactory(inferenceComponents, callInfo)
|
||||
val explicitReceiver = callInfo.explicitReceiver
|
||||
@@ -453,39 +513,40 @@ fun createSimpleConsumer(
|
||||
val receiverValue = ExpressionReceiverValue(explicitReceiver, callInfo.typeProvider)
|
||||
if (explicitReceiver is FirResolvedQualifier) {
|
||||
val qualified =
|
||||
QualifiedReceiverTowerDataConsumer(session, name, token, receiverValue, factory)
|
||||
QualifiedReceiverTowerDataConsumer(session, name, token, receiverValue, factory, resultCollector)
|
||||
|
||||
if (explicitReceiver.classId != null) {
|
||||
PrioritizedTowerDataConsumer(
|
||||
resultCollector,
|
||||
qualified,
|
||||
ExplicitReceiverTowerDataConsumer(session, name, token, receiverValue, factory)
|
||||
ExplicitReceiverTowerDataConsumer(session, name, token, receiverValue, factory, resultCollector)
|
||||
)
|
||||
} else {
|
||||
qualified
|
||||
}
|
||||
|
||||
} else {
|
||||
ExplicitReceiverTowerDataConsumer(session, name, token, receiverValue, factory)
|
||||
ExplicitReceiverTowerDataConsumer(session, name, token, receiverValue, factory, resultCollector)
|
||||
}
|
||||
} else {
|
||||
NoExplicitReceiverTowerDataConsumer(session, name, token, factory)
|
||||
NoExplicitReceiverTowerDataConsumer(session, name, token, factory, resultCollector)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class PrioritizedTowerDataConsumer(
|
||||
val resultCollector: CandidateCollector,
|
||||
vararg val consumers: TowerDataConsumer
|
||||
) : TowerDataConsumer() {
|
||||
|
||||
override fun consume(
|
||||
kind: TowerDataKind,
|
||||
towerScopeLevel: TowerScopeLevel,
|
||||
resultCollector: CandidateCollector,
|
||||
group: Int
|
||||
): ProcessorAction {
|
||||
if (checkSkip(group, resultCollector)) return ProcessorAction.NEXT
|
||||
if (skipGroup(group, resultCollector)) return ProcessorAction.NEXT
|
||||
for ((index, consumer) in consumers.withIndex()) {
|
||||
val action = consumer.consume(kind, towerScopeLevel, resultCollector, group * consumers.size + index)
|
||||
val action = consumer.consume(kind, towerScopeLevel, group * consumers.size + index)
|
||||
if (action.stop()) {
|
||||
return ProcessorAction.STOP
|
||||
}
|
||||
@@ -494,12 +555,57 @@ class PrioritizedTowerDataConsumer(
|
||||
}
|
||||
}
|
||||
|
||||
class MultiplexerTowerDataConsumer(
|
||||
val resultCollector: CandidateCollector
|
||||
) : TowerDataConsumer() {
|
||||
|
||||
val consumers = mutableListOf<TowerDataConsumer>()
|
||||
val newConsumers = mutableListOf<TowerDataConsumer>()
|
||||
|
||||
data class TowerData(val kind: TowerDataKind, val level: TowerScopeLevel, val group: Int)
|
||||
|
||||
val datas = mutableListOf<TowerData>()
|
||||
|
||||
override fun consume(
|
||||
kind: TowerDataKind,
|
||||
towerScopeLevel: TowerScopeLevel,
|
||||
group: Int
|
||||
): ProcessorAction {
|
||||
if (skipGroup(group, resultCollector)) return ProcessorAction.NEXT
|
||||
consumers += newConsumers
|
||||
newConsumers.clear()
|
||||
datas += TowerData(kind, towerScopeLevel, group)
|
||||
|
||||
for (consumer in consumers) {
|
||||
val action = consumer.consume(kind, towerScopeLevel, group)
|
||||
if (action.stop()) {
|
||||
return ProcessorAction.STOP
|
||||
}
|
||||
}
|
||||
return ProcessorAction.NEXT
|
||||
}
|
||||
|
||||
fun addConsumer(consumer: TowerDataConsumer): ProcessorAction =
|
||||
run {
|
||||
for ((kind, level, group) in datas) {
|
||||
if (consumer.consume(kind, level, group).stop()) {
|
||||
return@run ProcessorAction.STOP
|
||||
}
|
||||
}
|
||||
return@run ProcessorAction.NEXT
|
||||
}.also {
|
||||
newConsumers += consumer
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ExplicitReceiverTowerDataConsumer<T : ConeSymbol>(
|
||||
val session: FirSession,
|
||||
val name: Name,
|
||||
val token: TowerScopeLevel.Token<T>,
|
||||
val explicitReceiver: ExpressionReceiverValue,
|
||||
val candidateFactory: CandidateFactory
|
||||
val candidateFactory: CandidateFactory,
|
||||
val resultCollector: CandidateCollector
|
||||
) : TowerDataConsumer() {
|
||||
|
||||
companion object {
|
||||
@@ -510,10 +616,9 @@ class ExplicitReceiverTowerDataConsumer<T : ConeSymbol>(
|
||||
override fun consume(
|
||||
kind: TowerDataKind,
|
||||
towerScopeLevel: TowerScopeLevel,
|
||||
resultCollector: CandidateCollector,
|
||||
group: Int
|
||||
): ProcessorAction {
|
||||
if (checkSkip(group, resultCollector)) return ProcessorAction.NEXT
|
||||
if (skipGroup(group, resultCollector)) return ProcessorAction.NEXT
|
||||
return when (kind) {
|
||||
TowerDataKind.EMPTY ->
|
||||
MemberScopeTowerLevel(session, explicitReceiver, scopeSession = candidateFactory.inferenceComponents.scopeSession)
|
||||
@@ -598,17 +703,17 @@ class NoExplicitReceiverTowerDataConsumer<T : ConeSymbol>(
|
||||
val session: FirSession,
|
||||
val name: Name,
|
||||
val token: TowerScopeLevel.Token<T>,
|
||||
val candidateFactory: CandidateFactory
|
||||
val candidateFactory: CandidateFactory,
|
||||
val resultCollector: CandidateCollector
|
||||
) : TowerDataConsumer() {
|
||||
|
||||
|
||||
override fun consume(
|
||||
kind: TowerDataKind,
|
||||
towerScopeLevel: TowerScopeLevel,
|
||||
resultCollector: CandidateCollector,
|
||||
group: Int
|
||||
): ProcessorAction {
|
||||
if (checkSkip(group, resultCollector)) return ProcessorAction.NEXT
|
||||
if (skipGroup(group, resultCollector)) return ProcessorAction.NEXT
|
||||
return when (kind) {
|
||||
|
||||
TowerDataKind.TOWER_LEVEL -> {
|
||||
@@ -639,7 +744,6 @@ class NoExplicitReceiverTowerDataConsumer<T : ConeSymbol>(
|
||||
else -> ProcessorAction.NEXT
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class CallResolver(val typeCalculator: ReturnTypeCalculator, val components: InferenceComponents) {
|
||||
@@ -660,36 +764,41 @@ class CallResolver(val typeCalculator: ReturnTypeCalculator, val components: Inf
|
||||
towerDataConsumer.consume(
|
||||
TowerDataKind.TOWER_LEVEL,
|
||||
MemberScopeTowerLevel(session, implicitReceiverValue, scopeSession = components.scopeSession),
|
||||
collector, group++
|
||||
group++
|
||||
)
|
||||
|
||||
// This is an equivalent to the old "BothTowerLevelAndImplicitReceiver"
|
||||
towerDataConsumer.consume(
|
||||
TowerDataKind.TOWER_LEVEL,
|
||||
MemberScopeTowerLevel(session, implicitReceiverValue, implicitReceiverValue, components.scopeSession),
|
||||
collector, group++
|
||||
group++
|
||||
)
|
||||
|
||||
for (scope in scopes!!) {
|
||||
towerDataConsumer.consume(
|
||||
TowerDataKind.TOWER_LEVEL,
|
||||
ScopeTowerLevel(session, scope, implicitReceiverValue),
|
||||
collector, group++
|
||||
group++
|
||||
)
|
||||
}
|
||||
|
||||
return group
|
||||
}
|
||||
|
||||
fun runTowerResolver(towerDataConsumer: TowerDataConsumer, implicitReceiverValues: List<ImplicitReceiverValue>): CandidateCollector {
|
||||
val collector = CandidateCollector(callInfo!!, components)
|
||||
val collector by lazy { CandidateCollector(components) }
|
||||
lateinit var towerDataConsumer: TowerDataConsumer
|
||||
private lateinit var implicitReceiverValues: List<ImplicitReceiverValue>
|
||||
|
||||
fun runTowerResolver(consumer: TowerDataConsumer, implicitReceiverValues: List<ImplicitReceiverValue>): CandidateCollector {
|
||||
this.implicitReceiverValues = implicitReceiverValues
|
||||
towerDataConsumer = consumer
|
||||
|
||||
var group = 0
|
||||
|
||||
towerDataConsumer.consume(TowerDataKind.EMPTY, TowerScopeLevel.Empty, collector, group++)
|
||||
towerDataConsumer.consume(TowerDataKind.EMPTY, TowerScopeLevel.Empty, group++)
|
||||
|
||||
for (scope in scopes!!) {
|
||||
towerDataConsumer.consume(TowerDataKind.TOWER_LEVEL, ScopeTowerLevel(session, scope), collector, group++)
|
||||
towerDataConsumer.consume(TowerDataKind.TOWER_LEVEL, ScopeTowerLevel(session, scope), group++)
|
||||
}
|
||||
|
||||
var blockDispatchReceivers = false
|
||||
@@ -702,13 +811,14 @@ class CallResolver(val typeCalculator: ReturnTypeCalculator, val components: Inf
|
||||
blockDispatchReceivers = true
|
||||
}
|
||||
}
|
||||
processImplicitReceiver(towerDataConsumer, implicitReceiverValue, collector, group)
|
||||
group = processImplicitReceiver(towerDataConsumer, implicitReceiverValue, collector, group)
|
||||
}
|
||||
|
||||
|
||||
|
||||
return collector
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -721,7 +831,7 @@ enum class CandidateApplicability {
|
||||
RESOLVED
|
||||
}
|
||||
|
||||
class CandidateCollector(val callInfo: CallInfo, val components: InferenceComponents) {
|
||||
open class CandidateCollector(val components: InferenceComponents) {
|
||||
|
||||
val groupNumbers = mutableListOf<Int>()
|
||||
val candidates = mutableListOf<Candidate>()
|
||||
@@ -744,8 +854,8 @@ class CandidateCollector(val callInfo: CallInfo, val components: InferenceCompon
|
||||
val sink = CheckerSinkImpl(components)
|
||||
var finished = false
|
||||
sink.continuation = suspend {
|
||||
for (stage in callInfo.callKind.sequence()) {
|
||||
stage.check(candidate, sink, callInfo)
|
||||
for (stage in candidate.callInfo.callKind.sequence()) {
|
||||
stage.check(candidate, sink, candidate.callInfo)
|
||||
}
|
||||
}.createCoroutineUnintercepted(completion = object : Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
@@ -769,7 +879,7 @@ class CandidateCollector(val callInfo: CallInfo, val components: InferenceCompon
|
||||
return sink.current
|
||||
}
|
||||
|
||||
fun consumeCandidate(group: Int, candidate: Candidate) {
|
||||
open fun consumeCandidate(group: Int, candidate: Candidate): CandidateApplicability {
|
||||
val applicability = getApplicability(group, candidate)
|
||||
|
||||
if (applicability > currentApplicability) {
|
||||
@@ -783,6 +893,8 @@ class CandidateCollector(val callInfo: CallInfo, val components: InferenceCompon
|
||||
candidates.add(candidate)
|
||||
groupNumbers.add(group)
|
||||
}
|
||||
|
||||
return applicability
|
||||
}
|
||||
|
||||
|
||||
@@ -808,6 +920,47 @@ class CandidateCollector(val callInfo: CallInfo, val components: InferenceCompon
|
||||
}
|
||||
}
|
||||
|
||||
class InvokeCandidateCollector(
|
||||
val callResolver: CallResolver,
|
||||
val invokeCallInfo: CallInfo,
|
||||
components: InferenceComponents,
|
||||
val multiplexer: MultiplexerTowerDataConsumer
|
||||
) : CandidateCollector(components) {
|
||||
override fun consumeCandidate(group: Int, candidate: Candidate): CandidateApplicability {
|
||||
val applicability = super.consumeCandidate(group, candidate)
|
||||
|
||||
if (applicability >= CandidateApplicability.SYNTHETIC_RESOLVED) {
|
||||
|
||||
val session = components.session
|
||||
val boundInvokeCallInfo = CallInfo(
|
||||
invokeCallInfo.callKind,
|
||||
FirQualifiedAccessExpressionImpl(session, null, false).apply {
|
||||
calleeReference = FirNamedReferenceWithCandidate(
|
||||
session,
|
||||
null,
|
||||
(candidate.symbol as ConeCallableSymbol).callableId.callableName,
|
||||
candidate
|
||||
)
|
||||
typeRef = callResolver.typeCalculator.tryCalculateReturnType(candidate.symbol.firUnsafe())
|
||||
},
|
||||
invokeCallInfo.arguments,
|
||||
invokeCallInfo.isSafeCall,
|
||||
invokeCallInfo.typeArguments,
|
||||
session,
|
||||
invokeCallInfo.containingFile,
|
||||
invokeCallInfo.container,
|
||||
invokeCallInfo.typeProvider
|
||||
)
|
||||
val invokeConsumer =
|
||||
createSimpleFunctionConsumer(session, Name.identifier("invoke"), boundInvokeCallInfo, components, callResolver.collector)
|
||||
|
||||
multiplexer.addConsumer(invokeConsumer)
|
||||
}
|
||||
|
||||
return applicability
|
||||
}
|
||||
}
|
||||
|
||||
fun FirCallableDeclaration.dispatchReceiverValue(session: FirSession): ClassDispatchReceiverValue? {
|
||||
// TODO: this is not true at least for inner class constructors
|
||||
if (this is FirConstructor) return null
|
||||
|
||||
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
|
||||
class CandidateFactory(
|
||||
val inferenceComponents: InferenceComponents,
|
||||
callInfo: CallInfo
|
||||
val callInfo: CallInfo
|
||||
) {
|
||||
|
||||
val baseSystem: ConstraintStorage
|
||||
@@ -35,7 +35,7 @@ class CandidateFactory(
|
||||
): Candidate {
|
||||
return Candidate(
|
||||
symbol, dispatchReceiverValue, implicitExtensionReceiverValue,
|
||||
explicitReceiverKind, inferenceComponents, baseSystem
|
||||
explicitReceiverKind, inferenceComponents, baseSystem, callInfo
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+78
-9
@@ -15,8 +15,7 @@ import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirClassImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirEnumEntryImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.*
|
||||
import org.jetbrains.kotlin.fir.deserialization.FirBuiltinAnnotationDeserializer
|
||||
import org.jetbrains.kotlin.fir.deserialization.FirDeserializationContext
|
||||
import org.jetbrains.kotlin.fir.deserialization.deserializeClassToSymbol
|
||||
@@ -24,11 +23,12 @@ import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.firUnsafe
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirClassDeclaredMemberScope
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.*
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.builtins.BuiltInsBinaryVersion
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl
|
||||
@@ -38,6 +38,8 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ProtoBasedClassDataFinder
|
||||
import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getName
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
import java.io.InputStream
|
||||
|
||||
@@ -168,15 +170,82 @@ class FirLibrarySymbolProviderImpl(val session: FirSession) : FirSymbolProvider(
|
||||
this,
|
||||
relativeClassName.shortName(),
|
||||
Visibilities.PUBLIC,
|
||||
Modality.OPEN,
|
||||
Modality.ABSTRACT,
|
||||
isExpect = false,
|
||||
isActual = false,
|
||||
classKind = ClassKind.CLASS,
|
||||
classKind = ClassKind.INTERFACE,
|
||||
isInner = false,
|
||||
isCompanion = false,
|
||||
isData = false,
|
||||
isInline = false
|
||||
)
|
||||
).apply klass@{
|
||||
typeParameters.addAll((1..arity).map {
|
||||
FirTypeParameterImpl(
|
||||
session,
|
||||
null,
|
||||
FirTypeParameterSymbol(),
|
||||
Name.identifier("P$it"),
|
||||
Variance.IN_VARIANCE,
|
||||
false
|
||||
)
|
||||
})
|
||||
typeParameters.add(
|
||||
FirTypeParameterImpl(
|
||||
session,
|
||||
null,
|
||||
FirTypeParameterSymbol(),
|
||||
Name.identifier("R"),
|
||||
Variance.OUT_VARIANCE,
|
||||
false
|
||||
)
|
||||
)
|
||||
val name = Name.identifier("invoke")
|
||||
addDeclaration(
|
||||
FirMemberFunctionImpl(
|
||||
session,
|
||||
null,
|
||||
FirFunctionSymbol(CallableId(packageFqName, relativeClassName, name)),
|
||||
name,
|
||||
Visibilities.PUBLIC,
|
||||
Modality.ABSTRACT,
|
||||
isExpect = false,
|
||||
isActual = false,
|
||||
isOverride = false,
|
||||
isOperator = true,
|
||||
isInfix = false,
|
||||
isInline = false,
|
||||
isTailRec = false,
|
||||
isExternal = false,
|
||||
isSuspend = false,
|
||||
receiverTypeRef = null,
|
||||
returnTypeRef = FirResolvedTypeRefImpl(
|
||||
session,
|
||||
null,
|
||||
ConeTypeParameterTypeImpl(
|
||||
typeParameters.last().symbol.toLookupTag(),
|
||||
false
|
||||
)
|
||||
)
|
||||
).apply {
|
||||
valueParameters += this@klass.typeParameters.dropLast(1).map { typeParameter ->
|
||||
FirValueParameterImpl(
|
||||
session,
|
||||
null,
|
||||
Name.identifier(typeParameter.name.asString().toLowerCase()),
|
||||
FirResolvedTypeRefImpl(
|
||||
session,
|
||||
null,
|
||||
ConeTypeParameterTypeImpl(typeParameter.symbol.toLookupTag(), false)
|
||||
),
|
||||
defaultValue = null,
|
||||
isCrossinline = false,
|
||||
isNoinline = false,
|
||||
isVararg = false
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+31
-6
@@ -335,7 +335,8 @@ open class FirBodyResolveTransformer(
|
||||
val consumer = createVariableAndObjectConsumer(
|
||||
session,
|
||||
callee.name,
|
||||
info, inferenceComponents
|
||||
info, inferenceComponents,
|
||||
resolver.collector
|
||||
)
|
||||
val result = resolver.runTowerResolver(consumer, implicitReceiverStack.asReversed())
|
||||
|
||||
@@ -550,7 +551,7 @@ open class FirBodyResolveTransformer(
|
||||
resolver.callInfo = info
|
||||
resolver.scopes = (scopes + localScopes).asReversed()
|
||||
|
||||
val consumer = createFunctionConsumer(session, name, info, inferenceComponents)
|
||||
val consumer = createFunctionConsumer(session, name, info, inferenceComponents, resolver.collector, resolver)
|
||||
val result = resolver.runTowerResolver(consumer, implicitReceiverStack.asReversed())
|
||||
val bestCandidates = result.bestCandidates()
|
||||
val reducedCandidates = if (result.currentApplicability < CandidateApplicability.SYNTHETIC_RESOLVED) {
|
||||
@@ -596,11 +597,23 @@ open class FirBodyResolveTransformer(
|
||||
)
|
||||
|
||||
val resultExpression = functionCall.transformCalleeReference(StoreNameReference, nameReference) as FirFunctionCall
|
||||
val typeRef = typeFromCallee(functionCall)
|
||||
if (typeRef.type is ConeKotlinErrorType) {
|
||||
functionCall.resultType = typeRef
|
||||
val candidate = resultExpression.candidate()
|
||||
|
||||
// We need desugaring
|
||||
val resultFunctionCall = if (candidate != null && candidate.callInfo != info) {
|
||||
functionCall.copy(
|
||||
explicitReceiver = candidate.callInfo.explicitReceiver,
|
||||
arguments = candidate.callInfo.arguments,
|
||||
safe = candidate.callInfo.isSafeCall
|
||||
)
|
||||
} else {
|
||||
resultExpression
|
||||
}
|
||||
return resultExpression
|
||||
val typeRef = typeFromCallee(resultFunctionCall)
|
||||
if (typeRef.type is ConeKotlinErrorType) {
|
||||
resultFunctionCall.resultType = typeRef
|
||||
}
|
||||
return resultFunctionCall
|
||||
}
|
||||
|
||||
data class LambdaResolution(val expectedReturnTypeRef: FirResolvedTypeRef?)
|
||||
@@ -1270,6 +1283,18 @@ internal object StoreType : FirTransformer<FirTypeRef>() {
|
||||
}
|
||||
}
|
||||
|
||||
internal object StoreExplicitReceiver : FirTransformer<FirExpression>() {
|
||||
override fun <E : FirElement> transformElement(element: E, data: FirExpression): CompositeTransformResult<E> {
|
||||
return element.compose()
|
||||
}
|
||||
|
||||
override fun transformExpression(expression: FirExpression, data: FirExpression): CompositeTransformResult<FirStatement> {
|
||||
return data.compose()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private object ReplaceInArguments : FirTransformer<Map<FirElement, FirElement>>() {
|
||||
override fun <E : FirElement> transformElement(element: E, data: Map<FirElement, FirElement>): CompositeTransformResult<E> {
|
||||
return ((data[element] ?: element) as E).compose()
|
||||
|
||||
+2
-2
@@ -13,8 +13,8 @@ FILE: explicitReceiver.kt
|
||||
^invoke this#
|
||||
}
|
||||
|
||||
public final fun bar(): R|kotlin/Unit| {
|
||||
^bar R|/x|()
|
||||
public final fun bar(): R|Foo| {
|
||||
^bar R|/Foo.x|.R|/Foo.invoke|()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -23,8 +23,8 @@ FILE: explicitReceiver2.kt
|
||||
public final val x: R|Bar| = R|/Bar.Bar|()
|
||||
public get(): R|Bar|
|
||||
|
||||
public final fun bar(): R|kotlin/Unit| {
|
||||
^bar R|/x|()
|
||||
public final fun bar(): R|Foo| {
|
||||
^bar R|/Foo.x|.R|/Bar.invoke|()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,5 +7,5 @@ class Foo {
|
||||
|
||||
val x = 0
|
||||
|
||||
fun foo() = x()
|
||||
fun foo() = x() // should resolve to invoke
|
||||
}
|
||||
+1
-1
@@ -8,5 +8,5 @@ class Foo {
|
||||
|
||||
val x = 0
|
||||
|
||||
fun foo() = x()
|
||||
fun foo() = x() // should resolve to fun x
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
|
||||
class A {
|
||||
fun bar() = foo()
|
||||
fun bar() = foo() // should resolve to invoke
|
||||
|
||||
fun invoke() = this
|
||||
}
|
||||
|
||||
+2
-2
@@ -4,8 +4,8 @@ FILE: implicitTypeOrder.kt
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final fun bar(): <ERROR TYPE REF: Unresolved name: foo> {
|
||||
^bar <Unresolved name: foo>#()
|
||||
public final fun bar(): R|A| {
|
||||
^bar R|/foo|.R|/A.invoke|()
|
||||
}
|
||||
|
||||
public final fun invoke(): R|A| {
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
class Simple {
|
||||
operator fun invoke(): String = "invoke"
|
||||
}
|
||||
|
||||
fun test(s: Simple) {
|
||||
val result = s()
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
FILE: simple.kt
|
||||
public final class Simple : R|kotlin/Any| {
|
||||
public constructor(): R|Simple| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final operator fun invoke(): R|kotlin/String| {
|
||||
^invoke String(invoke)
|
||||
}
|
||||
|
||||
}
|
||||
public final fun test(s: R|Simple|): R|kotlin/Unit| {
|
||||
lval result: R|kotlin/String| = R|<local>/s|.R|/Simple.invoke|()
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
fun <T> simpleRun(f: (T) -> Unit): Unit = f()
|
||||
fun <T> simpleRun(f: (T) -> Unit): Unit = f(return)
|
||||
|
||||
fun <T, R> List<T>.simpleMap(f: (T) -> R): R {
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
FILE: functionTypes.kt
|
||||
public final fun <T> simpleRun(f: R|kotlin/Function1<T, kotlin/Unit>|): R|kotlin/Unit| {
|
||||
^simpleRun <Unresolved name: f>#()
|
||||
^simpleRun R|<local>/f|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(^simpleRun Unit)
|
||||
}
|
||||
public final fun <T, R> R|kotlin/collections/List<T>|.simpleMap(f: R|kotlin/Function1<T, R>|): R|R| {
|
||||
}
|
||||
|
||||
+5
@@ -372,6 +372,11 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/implicitTypeOrder.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/simple.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("threeReceivers.kt")
|
||||
public void testThreeReceivers() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/threeReceivers.kt");
|
||||
|
||||
Reference in New Issue
Block a user