From abfe566255ea87bd24c3c66d0e13be78ecdbb595 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Wed, 12 Feb 2020 18:08:41 +0300 Subject: [PATCH] [FIR] Add object support as implicit invoke receiver --- .../fir/resolve/calls/TowerResolveManager.kt | 27 +++++++++++++++---- .../problems/invokePriority.txt | 2 +- ...nvokeInObjectWithFunctionalArgument.fir.kt | 8 +++--- ...edClassAccessedViaInstanceReference.fir.kt | 6 ++--- .../tests/operatorsOverloading/kt13349.fir.kt | 2 +- .../expressions/objectAsCallable.fir.txt | 13 ++++----- 6 files changed, 38 insertions(+), 20 deletions(-) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerResolveManager.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerResolveManager.kt index d34f998c1f5..51e68a4bbd0 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerResolveManager.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerResolveManager.kt @@ -9,13 +9,16 @@ import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier import org.jetbrains.kotlin.fir.expressions.builder.FirQualifiedAccessExpressionBuilder import org.jetbrains.kotlin.fir.resolve.constructClassType +import org.jetbrains.kotlin.fir.resolve.constructType import org.jetbrains.kotlin.fir.resolve.transformQualifiedAccessUsingSmartcastInfo import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind @@ -106,15 +109,25 @@ class TowerResolveManager internal constructor(private val towerResolver: FirTow val group: TowerGroup ) { private fun createExplicitReceiverForInvoke(candidate: Candidate): FirQualifiedAccessExpressionBuilder { - val symbol = candidate.symbol as FirCallableSymbol<*> + val (name, typeRef) = when (val symbol = candidate.symbol) { + is FirCallableSymbol<*> -> { + symbol.callableId.callableName to towerResolver.typeCalculator.tryCalculateReturnType(symbol.firUnsafe()) + } + is FirRegularClassSymbol -> { + symbol.classId.shortClassName to buildResolvedTypeRef { + type = symbol.constructType(emptyArray(), isNullable = false) + } + } + else -> throw AssertionError() + } return FirQualifiedAccessExpressionBuilder().apply { calleeReference = FirNamedReferenceWithCandidate( null, - symbol.callableId.callableName, + name, candidate ) dispatchReceiver = candidate.dispatchReceiverExpression() - typeRef = towerResolver.typeCalculator.tryCalculateReturnType(symbol.firUnsafe()) + this.typeRef = typeRef } } @@ -163,12 +176,16 @@ class TowerResolveManager internal constructor(private val towerResolver: FirTow ) invokeReceiverCollector.newDataSet() result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, invokeReceiverProcessor) + if (this !is ScopeTowerLevel || this.extensionReceiver == null) { + result += processElementsByName(TowerScopeLevel.Token.Objects, info.name, invokeReceiverProcessor) + } if (invokeReceiverCollector.isSuccess()) { for (invokeReceiverCandidate in invokeReceiverCollector.bestCandidates()) { - val symbol = invokeReceiverCandidate.symbol as FirCallableSymbol<*> - val isExtensionFunctionType = symbol.fir.returnTypeRef.isExtensionFunctionType(towerResolver.components.session) + val symbol = invokeReceiverCandidate.symbol + if (symbol !is FirCallableSymbol<*> && symbol !is FirRegularClassSymbol) continue + val isExtensionFunctionType = (symbol as? FirCallableSymbol<*>)?.fir?.returnTypeRef?.isExtensionFunctionType(towerResolver.components.session) == true if (invokeBuiltinExtensionMode && !isExtensionFunctionType) { continue } diff --git a/compiler/fir/resolve/testData/resolveWithStdlib/problems/invokePriority.txt b/compiler/fir/resolve/testData/resolveWithStdlib/problems/invokePriority.txt index 76b64314afc..5ed5662a409 100644 --- a/compiler/fir/resolve/testData/resolveWithStdlib/problems/invokePriority.txt +++ b/compiler/fir/resolve/testData/resolveWithStdlib/problems/invokePriority.txt @@ -74,6 +74,6 @@ FILE: invokePriority.kt } public final fun main(): R|kotlin/Unit| { - Q|E|.R|/E.Companion.f|.R|FakeOverride|() + Q|E|.R|/E.Companion.f|.R|/E.f.invoke|() Q|E.f|.R|/E.f.invoke|() } diff --git a/compiler/testData/diagnostics/tests/inference/implicitInvokeInObjectWithFunctionalArgument.fir.kt b/compiler/testData/diagnostics/tests/inference/implicitInvokeInObjectWithFunctionalArgument.fir.kt index 88ee2013734..9b445a43789 100644 --- a/compiler/testData/diagnostics/tests/inference/implicitInvokeInObjectWithFunctionalArgument.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/implicitInvokeInObjectWithFunctionalArgument.fir.kt @@ -7,9 +7,9 @@ object TestClass { } fun test(s: String): String { - val a = TestClass { TestClass { TestClass } } - a checkType { _() } + val a = TestClass { TestClass { TestClass } } + a checkType { _() } - val b = TestClass { return s } - b checkType { _() } + val b = TestClass { return s } + b checkType { _() } } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inner/nestedClassAccessedViaInstanceReference.fir.kt b/compiler/testData/diagnostics/tests/inner/nestedClassAccessedViaInstanceReference.fir.kt index 41abe184ac5..69bdc184c13 100644 --- a/compiler/testData/diagnostics/tests/inner/nestedClassAccessedViaInstanceReference.fir.kt +++ b/compiler/testData/diagnostics/tests/inner/nestedClassAccessedViaInstanceReference.fir.kt @@ -30,7 +30,7 @@ fun test(with: WithClassObject, without: WithoutClassObject, obj: Obj) { with.NestedWithClassObject.foo() with.NestedEnum.A with.NestedObj - with.NestedObj() + with.NestedObj() with.NestedObj.foo() without.Nested() @@ -39,7 +39,7 @@ fun test(with: WithClassObject, without: WithoutClassObject, obj: Obj) { without.NestedWithClassObject.foo() without.NestedEnum.A without.NestedObj - without.NestedObj() + without.NestedObj() without.NestedObj.foo() obj.Nested() @@ -48,6 +48,6 @@ fun test(with: WithClassObject, without: WithoutClassObject, obj: Obj) { obj.NestedWithClassObject.foo() obj.NestedEnum.A obj.NestedObj - obj.NestedObj() + obj.NestedObj() obj.NestedObj.foo() } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/operatorsOverloading/kt13349.fir.kt b/compiler/testData/diagnostics/tests/operatorsOverloading/kt13349.fir.kt index b3c73e430df..e2cb9f6115d 100644 --- a/compiler/testData/diagnostics/tests/operatorsOverloading/kt13349.fir.kt +++ b/compiler/testData/diagnostics/tests/operatorsOverloading/kt13349.fir.kt @@ -3,5 +3,5 @@ object Foo { } fun main() { - Foo() + Foo() } \ No newline at end of file diff --git a/compiler/testData/ir/irText/expressions/objectAsCallable.fir.txt b/compiler/testData/ir/irText/expressions/objectAsCallable.fir.txt index 90c37e895f4..2a364577aab 100644 --- a/compiler/testData/ir/irText/expressions/objectAsCallable.fir.txt +++ b/compiler/testData/ir/irText/expressions/objectAsCallable.fir.txt @@ -85,15 +85,16 @@ FILE fqName: fileName:/objectAsCallable.kt RETURN type=kotlin.Nothing from='public final fun invoke (i: kotlin.Int): kotlin.Int [operator] declared in ' GET_VAR 'i: kotlin.Int declared in .invoke' type=kotlin.Int origin=null PROPERTY name:test1 visibility:public modality:FINAL [val] - FIELD PROPERTY_BACKING_FIELD name:test1 type:IrErrorType visibility:private [final,static] + FIELD PROPERTY_BACKING_FIELD name:test1 type:kotlin.Int visibility:private [final,static] EXPRESSION_BODY - ERROR_CALL 'Unresolved reference: #' type=IrErrorType - CONST Int type=kotlin.Int value=42 - FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:IrErrorType + CALL 'public final fun invoke (i: kotlin.Int): kotlin.Int [operator] declared in ' type=kotlin.Int origin=null + $receiver: ERROR_CALL 'Unresolved reference: R|/A|' type=IrErrorType + i: CONST Int type=kotlin.Int value=42 + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Int correspondingProperty: PROPERTY name:test1 visibility:public modality:FINAL [val] BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun (): IrErrorType declared in ' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test1 type:IrErrorType visibility:private [final,static]' type=IrErrorType origin=null + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in ' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test1 type:kotlin.Int visibility:private [final,static]' type=kotlin.Int origin=null PROPERTY name:test2 visibility:public modality:FINAL [val] FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Int visibility:private [final,static] EXPRESSION_BODY