FIR: Support callable references to properties

^KT-32725 In Progress
This commit is contained in:
Denis Zharkov
2019-10-21 18:17:45 +03:00
parent 38ab6521aa
commit 74b9ba1613
8 changed files with 86 additions and 11 deletions
@@ -226,6 +226,15 @@ fun createFunctionalType(
return ConeClassTypeImpl(ConeClassLikeLookupTagImpl(functionalTypeId), receiverAndParameterTypes.toTypedArray(), isNullable = false)
}
fun createKPropertyType(
receiverType: ConeKotlinType?,
rawReturnType: ConeKotlinType
): ConeLookupTagBasedType {
val arguments = if (receiverType != null) listOf(receiverType, rawReturnType) else listOf(rawReturnType)
val classId = StandardClassIds.reflectByName("KProperty${arguments.size - 1}")
return ConeClassTypeImpl(ConeClassLikeLookupTagImpl(classId), arguments.toTypedArray(), isNullable = false)
}
fun BodyResolveComponents.typeForQualifier(resolvedQualifier: FirResolvedQualifier): FirTypeRef {
val classId = resolvedQualifier.classId
val resultType = resolvedQualifier.resultType
@@ -150,8 +150,7 @@ fun createCallableReferencesConsumer(
// TODO: Use SamePriorityConsumer
return PrioritizedTowerDataConsumer(
resultCollector,
createSimpleConsumer(session, name, TowerScopeLevel.Token.Functions, callInfo, bodyResolveComponents, resultCollector)
// TODO: Support properties
// , createSimpleConsumer(session, name, TowerScopeLevel.Token.Properties, callInfo, bodyResolveComponents, resultCollector)
createSimpleConsumer(session, name, TowerScopeLevel.Token.Functions, callInfo, bodyResolveComponents, resultCollector),
createSimpleConsumer(session, name, TowerScopeLevel.Token.Properties, callInfo, bodyResolveComponents, resultCollector)
)
}
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.declarations.visibility
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.resolve.DoubleColonLHS
import org.jetbrains.kotlin.fir.resolve.createFunctionalType
import org.jetbrains.kotlin.fir.resolve.createKPropertyType
import org.jetbrains.kotlin.fir.resolve.firProvider
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
@@ -185,7 +186,7 @@ internal object CheckCallableReferenceExpectedType : CheckerStage() {
val resultingType: ConeKotlinType = when (val fir = candidate.symbol.fir) {
is FirSimpleFunction -> createKFunctionType(fir, resultingReceiverType)
is FirProperty -> createKPropertyType(fir)
is FirProperty -> createKPropertyType(fir, resultingReceiverType)
else -> ConeKotlinErrorType("Unknown callable kind: ${fir::class}")
}.let(candidate.substitutor::substituteOrSelf)
@@ -210,8 +211,14 @@ internal object CheckCallableReferenceExpectedType : CheckerStage() {
}
}
private fun createKPropertyType(fir: FirProperty): ConeKotlinType {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
private fun createKPropertyType(
property: FirProperty,
receiverType: ConeKotlinType?
): ConeKotlinType {
val propertyType = property.returnTypeRef.coneTypeSafe<ConeKotlinType>() ?: ConeKotlinErrorType("No type for of $property")
return createKPropertyType(
receiverType, propertyType
)
}
private fun createKFunctionType(
@@ -16,7 +16,7 @@ FILE: noAmbiguityBetweenTopLevelAndMemberProperty.kt
public get(): R|kotlin/String|
}
public final val someProperty0: <ERROR TYPE REF: Inapplicable(INAPPLICABLE): [/property, /property]> = <Inapplicable(INAPPLICABLE): [/property, /property]>#(::subject#)
public get(): <ERROR TYPE REF: Inapplicable(INAPPLICABLE): [/property, /property]>
public final val someProperty1: <ERROR TYPE REF: Inapplicable(INAPPLICABLE): [/property, /property]> = <Inapplicable(INAPPLICABLE): [/property, /property]>#(Q|O|::subject#)
public get(): <ERROR TYPE REF: Inapplicable(INAPPLICABLE): [/property, /property]>
public final val someProperty0: R|kotlin/Int| = R|/property|<R|kotlin/String|>(::R|/subject|)
public get(): R|kotlin/Int|
public final val someProperty1: R|kotlin/String| = R|/property|<R|O|, R|kotlin/String|>(Q|O|::R|/O.subject|)
public get(): R|kotlin/String|
@@ -0,0 +1,23 @@
class A {
val bar: Int = 1
}
val bar = 1
val A.baz: Int get() = 1
fun foo1(x: () -> Int) {}
fun foo2(x: (A) -> Int) {}
fun <R> foo3(x: () -> R) {}
fun <T, R> foo4(x: (T) -> R) {}
fun main() {
foo1(::bar)
foo2(A::bar)
foo2(A::baz)
foo3(::bar)
foo4(A::bar)
foo4(A::baz)
}
@@ -0,0 +1,32 @@
FILE: properties.kt
public final class A : R|kotlin/Any| {
public constructor(): R|A| {
super<R|kotlin/Any|>()
}
public final val bar: R|kotlin/Int| = Int(1)
public get(): R|kotlin/Int|
}
public final val bar: R|kotlin/Int| = Int(1)
public get(): R|kotlin/Int|
public final val R|A|.baz: R|kotlin/Int|
public get(): R|kotlin/Int| {
^ Int(1)
}
public final fun foo1(x: R|kotlin/Function0<kotlin/Int>|): R|kotlin/Unit| {
}
public final fun foo2(x: R|kotlin/Function1<A, kotlin/Int>|): R|kotlin/Unit| {
}
public final fun <R> foo3(x: R|kotlin/Function0<R>|): R|kotlin/Unit| {
}
public final fun <T, R> foo4(x: R|kotlin/Function1<T, R>|): R|kotlin/Unit| {
}
public final fun main(): R|kotlin/Unit| {
R|/foo1|(::R|/bar|)
R|/foo2|(Q|A|::R|/A.bar|)
R|/foo2|(Q|A|::R|/baz|)
R|/foo3|<R|kotlin/Int|>(::R|/bar|)
R|/foo4|<R|A|, R|kotlin/Int|>(Q|A|::R|/A.bar|)
R|/foo4|<R|A|, R|kotlin/Int|>(Q|A|::R|/baz|)
}
@@ -23,5 +23,5 @@ FILE: extensionPropertyInLambda.kt
R|/C.C|<R|kotlin/String|>(String(abc)).R|/y|
}
)
R|/use|(R|/C.C|<R|kotlin/String|>(String(abc))::R|/y|)
R|/use|(R|/C.C|<R|kotlin/String|>(String(abc))::R|/y<kotlin/String>|)
}
@@ -90,6 +90,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/manyOuterCandidates.kt");
}
@TestMetadata("properties.kt")
public void testProperties() throws Exception {
runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/properties.kt");
}
@TestMetadata("simpleClassReceiver.kt")
public void testSimpleClassReceiver() throws Exception {
runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/simpleClassReceiver.kt");