FIR: partially implement invoke resolution

This commit is contained in:
Mikhail Glukhikh
2019-05-24 14:36:09 +03:00
parent 2ca0056cd0
commit d96c66adac
29 changed files with 433 additions and 153 deletions
@@ -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
)
}
}
@@ -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
)
}
}
)
}
}
}
}
@@ -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()
@@ -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|()
}
}
@@ -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
}
@@ -8,5 +8,5 @@ class Foo {
val x = 0
fun foo() = x()
fun foo() = x() // should resolve to fun x
}
@@ -1,6 +1,6 @@
class A {
fun bar() = foo()
fun bar() = foo() // should resolve to invoke
fun invoke() = this
}
@@ -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
View File
@@ -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
View File
@@ -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| {
}
@@ -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");