[FIR] Add object support as implicit invoke receiver

This commit is contained in:
Mikhail Glukhikh
2020-02-12 18:08:41 +03:00
parent a8a696c7e1
commit abfe566255
6 changed files with 38 additions and 20 deletions
@@ -9,13 +9,16 @@ import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.expressions.builder.FirQualifiedAccessExpressionBuilder import org.jetbrains.kotlin.fir.expressions.builder.FirQualifiedAccessExpressionBuilder
import org.jetbrains.kotlin.fir.resolve.constructClassType 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.transformQualifiedAccessUsingSmartcastInfo
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe
import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol 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.*
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
@@ -106,15 +109,25 @@ class TowerResolveManager internal constructor(private val towerResolver: FirTow
val group: TowerGroup val group: TowerGroup
) { ) {
private fun createExplicitReceiverForInvoke(candidate: Candidate): FirQualifiedAccessExpressionBuilder { 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 { return FirQualifiedAccessExpressionBuilder().apply {
calleeReference = FirNamedReferenceWithCandidate( calleeReference = FirNamedReferenceWithCandidate(
null, null,
symbol.callableId.callableName, name,
candidate candidate
) )
dispatchReceiver = candidate.dispatchReceiverExpression() 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() invokeReceiverCollector.newDataSet()
result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, invokeReceiverProcessor) 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()) { if (invokeReceiverCollector.isSuccess()) {
for (invokeReceiverCandidate in invokeReceiverCollector.bestCandidates()) { for (invokeReceiverCandidate in invokeReceiverCollector.bestCandidates()) {
val symbol = invokeReceiverCandidate.symbol as FirCallableSymbol<*> val symbol = invokeReceiverCandidate.symbol
val isExtensionFunctionType = symbol.fir.returnTypeRef.isExtensionFunctionType(towerResolver.components.session) if (symbol !is FirCallableSymbol<*> && symbol !is FirRegularClassSymbol) continue
val isExtensionFunctionType = (symbol as? FirCallableSymbol<*>)?.fir?.returnTypeRef?.isExtensionFunctionType(towerResolver.components.session) == true
if (invokeBuiltinExtensionMode && !isExtensionFunctionType) { if (invokeBuiltinExtensionMode && !isExtensionFunctionType) {
continue continue
} }
@@ -74,6 +74,6 @@ FILE: invokePriority.kt
} }
public final fun main(): R|kotlin/Unit| { public final fun main(): R|kotlin/Unit| {
Q|E|.R|/E.Companion.f|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|() Q|E|.R|/E.Companion.f|.R|/E.f.invoke|()
Q|E.f|.R|/E.f.invoke|() Q|E.f|.R|/E.f.invoke|()
} }
@@ -7,9 +7,9 @@ object TestClass {
} }
fun test(s: String): String { fun test(s: String): String {
val a = <!INAPPLICABLE_CANDIDATE!>TestClass<!> { <!INAPPLICABLE_CANDIDATE!>TestClass<!> { TestClass } } val a = TestClass { TestClass { TestClass } }
a <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><TestClass>() } a checkType { <!UNRESOLVED_REFERENCE!>_<!><TestClass>() }
val b = <!INAPPLICABLE_CANDIDATE!>TestClass<!> { return s } val b = TestClass { return s }
b <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><Nothing>() } b checkType { <!UNRESOLVED_REFERENCE!>_<!><Nothing>() }
} }
@@ -30,7 +30,7 @@ fun test(with: WithClassObject, without: WithoutClassObject, obj: Obj) {
with.NestedWithClassObject.foo() with.NestedWithClassObject.foo()
with.NestedEnum.A with.NestedEnum.A
with.NestedObj with.NestedObj
with.<!UNRESOLVED_REFERENCE!>NestedObj<!>() with.NestedObj()
with.NestedObj.foo() with.NestedObj.foo()
without.<!UNRESOLVED_REFERENCE!>Nested<!>() without.<!UNRESOLVED_REFERENCE!>Nested<!>()
@@ -39,7 +39,7 @@ fun test(with: WithClassObject, without: WithoutClassObject, obj: Obj) {
without.NestedWithClassObject.foo() without.NestedWithClassObject.foo()
without.NestedEnum.A without.NestedEnum.A
without.NestedObj without.NestedObj
without.<!UNRESOLVED_REFERENCE!>NestedObj<!>() without.NestedObj()
without.NestedObj.foo() without.NestedObj.foo()
obj.<!UNRESOLVED_REFERENCE!>Nested<!>() obj.<!UNRESOLVED_REFERENCE!>Nested<!>()
@@ -48,6 +48,6 @@ fun test(with: WithClassObject, without: WithoutClassObject, obj: Obj) {
obj.NestedWithClassObject.foo() obj.NestedWithClassObject.foo()
obj.NestedEnum.A obj.NestedEnum.A
obj.NestedObj obj.NestedObj
obj.<!UNRESOLVED_REFERENCE!>NestedObj<!>() obj.NestedObj()
obj.NestedObj.foo() obj.NestedObj.foo()
} }
@@ -3,5 +3,5 @@ object Foo {
} }
fun main() { fun main() {
<!INAPPLICABLE_CANDIDATE!>Foo<!><Int>() Foo<Int>()
} }
@@ -85,15 +85,16 @@ FILE fqName:<root> fileName:/objectAsCallable.kt
RETURN type=kotlin.Nothing from='public final fun invoke (i: kotlin.Int): kotlin.Int [operator] declared in <root>' RETURN type=kotlin.Nothing from='public final fun invoke (i: kotlin.Int): kotlin.Int [operator] declared in <root>'
GET_VAR 'i: kotlin.Int declared in <root>.invoke' type=kotlin.Int origin=null GET_VAR 'i: kotlin.Int declared in <root>.invoke' type=kotlin.Int origin=null
PROPERTY name:test1 visibility:public modality:FINAL [val] 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 EXPRESSION_BODY
ERROR_CALL 'Unresolved reference: <Inapplicable(HIDDEN): [/A.A]>#' type=IrErrorType CALL 'public final fun invoke (i: kotlin.Int): kotlin.Int [operator] declared in <root>' type=kotlin.Int origin=null
CONST Int type=kotlin.Int value=42 $receiver: ERROR_CALL 'Unresolved reference: R|/A|' type=IrErrorType
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test1> visibility:public modality:FINAL <> () returnType:IrErrorType i: CONST Int type=kotlin.Int value=42
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test1> visibility:public modality:FINAL <> () returnType:kotlin.Int
correspondingProperty: PROPERTY name:test1 visibility:public modality:FINAL [val] correspondingProperty: PROPERTY name:test1 visibility:public modality:FINAL [val]
BLOCK_BODY BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-test1> (): IrErrorType declared in <root>' RETURN type=kotlin.Nothing from='public final fun <get-test1> (): kotlin.Int declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test1 type:IrErrorType visibility:private [final,static]' type=IrErrorType origin=null 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] PROPERTY name:test2 visibility:public modality:FINAL [val]
FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Int visibility:private [final,static] FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Int visibility:private [final,static]
EXPRESSION_BODY EXPRESSION_BODY