FIR resolve: support inferring property type from getter

This commit is contained in:
Mikhail Glukhikh
2019-05-27 17:46:49 +03:00
parent 16ead49967
commit 54078c4e9c
11 changed files with 193 additions and 116 deletions
@@ -94,21 +94,12 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
return data.compose()
}
override fun transformFunction(function: FirFunction, data: Any?): CompositeTransformResult<FirDeclaration> {
return withScopeCleanup(localScopes) {
localScopes += FirLocalScope()
super.transformFunction(function, data)
}
}
override fun transformValueParameter(valueParameter: FirValueParameter, data: Any?): CompositeTransformResult<FirDeclaration> {
localScopes.lastOrNull()?.storeDeclaration(valueParameter)
if (valueParameter.returnTypeRef is FirImplicitTypeRef) return valueParameter.compose() // TODO
return super.transformValueParameter(valueParameter, valueParameter.returnTypeRef)
}
private inline fun <T> withLabelAndReceiverType(labelName: Name, owner: FirElement, type: ConeKotlinType, block: () -> T): T {
labels.put(labelName, type)
when (owner) {
@@ -871,34 +862,69 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
return (annotationCall.transformChildren(this, data) as FirStatement).compose()
}
override fun transformFunction(function: FirFunction, data: Any?): CompositeTransformResult<FirDeclaration> {
return withScopeCleanup(localScopes) {
localScopes += FirLocalScope()
super.transformFunction(function, data)
}
}
private fun transformFunctionWithGivenSignature(
function: FirFunction,
returnTypeRef: FirTypeRef,
receiverTypeRef: FirTypeRef? = null
): CompositeTransformResult<FirDeclaration> {
if (function is FirNamedFunction) {
localScopes.lastOrNull()?.storeDeclaration(function)
}
return withScopeCleanup(scopes) {
scopes.addIfNotNull(receiverTypeRef?.coneTypeSafe<ConeKotlinType>()?.scope(session, scopeSession))
val result = transformFunction(function, returnTypeRef).single as FirFunction
val body = result.body
if (result is FirTypedDeclaration && result.returnTypeRef is FirImplicitTypeRef && body != null) {
result.transformReturnTypeRef(this, body.resultType)
result
} else {
result
}.compose()
}
}
override fun transformNamedFunction(namedFunction: FirNamedFunction, data: Any?): CompositeTransformResult<FirDeclaration> {
if (namedFunction.returnTypeRef !is FirImplicitTypeRef && implicitTypeOnly) return namedFunction.compose()
if (namedFunction.returnTypeRef is FirImplicitTypeRef) {
val returnTypeRef = namedFunction.returnTypeRef
if ((returnTypeRef !is FirImplicitTypeRef || returnTypeRef is FirResolvedTypeRef) && implicitTypeOnly) {
return namedFunction.compose()
}
if (returnTypeRef is FirImplicitTypeRef && returnTypeRef !is FirResolvedTypeRef) {
namedFunction.transformReturnTypeRef(StoreType, FirComputingImplicitTypeRef)
}
val receiverTypeRef = namedFunction.receiverTypeRef
fun transform(): CompositeTransformResult<FirDeclaration> {
localScopes.lastOrNull()?.storeDeclaration(namedFunction)
return withScopeCleanup(scopes) {
scopes.addIfNotNull(receiverTypeRef?.coneTypeSafe<ConeKotlinType>()?.scope(session, scopeSession))
val result = super.transformNamedFunction(namedFunction, namedFunction.returnTypeRef).single as FirNamedFunction
val body = result.body
if (result.returnTypeRef is FirImplicitTypeRef && body != null) {
result.transformReturnTypeRef(this, body.resultType)
result
} else {
result
}.compose()
}
}
return if (receiverTypeRef != null) {
withLabelAndReceiverType(namedFunction.name, namedFunction, receiverTypeRef.coneTypeUnsafe()) { transform() }
withLabelAndReceiverType(namedFunction.name, namedFunction, receiverTypeRef.coneTypeUnsafe()) {
transformFunctionWithGivenSignature(namedFunction, returnTypeRef, receiverTypeRef)
}
} else {
transform()
transformFunctionWithGivenSignature(namedFunction, returnTypeRef)
}
}
override fun transformPropertyAccessor(propertyAccessor: FirPropertyAccessor, data: Any?): CompositeTransformResult<FirDeclaration> {
if (propertyAccessor is FirDefaultPropertyAccessor || propertyAccessor.body == null) {
return super.transformPropertyAccessor(propertyAccessor, data)
}
val returnTypeRef = propertyAccessor.returnTypeRef
if ((returnTypeRef !is FirImplicitTypeRef || returnTypeRef is FirResolvedTypeRef) && implicitTypeOnly) {
return propertyAccessor.compose()
}
if (returnTypeRef is FirImplicitTypeRef && returnTypeRef !is FirResolvedTypeRef && data !is FirResolvedTypeRef) {
propertyAccessor.transformReturnTypeRef(StoreType, FirComputingImplicitTypeRef)
}
return if (data is FirResolvedTypeRef && returnTypeRef !is FirResolvedTypeRef) {
transformFunctionWithGivenSignature(propertyAccessor, data)
} else {
transformFunctionWithGivenSignature(propertyAccessor, returnTypeRef)
}
}
@@ -933,17 +959,22 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
)
)
}
else -> {
variable is FirProperty && variable.getter !is FirDefaultPropertyAccessor -> {
variable.transformReturnTypeRef(
this,
FirErrorTypeRefImpl(
session, null,
if (variable is FirProperty && variable.getter !is FirDefaultPropertyAccessor) {
"Not supported: type from property getter"
} else {
"Cannot infer variable type without initializer / getter / delegate"
}
)
when (val resultType = variable.getter.returnTypeRef) {
is FirImplicitTypeRef -> FirErrorTypeRefImpl(
session,
null,
"No result type for getter"
)
else -> resultType
}
)
}
else -> {
variable.transformReturnTypeRef(
this, FirErrorTypeRefImpl(session, null, "Cannot infer variable type without initializer / getter / delegate")
)
}
}
@@ -966,13 +997,19 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
localScopes.addIfNotNull(primaryConstructorParametersScope)
withContainer(property) {
property.transformChildrenWithoutAccessors(this, returnTypeRef)
storeVariableReturnType(property)
if (property.returnTypeRef is FirImplicitTypeRef && property.initializer != null) {
storeVariableReturnType(property)
}
withScopeCleanup(localScopes) {
localScopes.add(FirLocalScope().apply {
storeBackingField(property)
})
val enhancedTypeRef = property.returnTypeRef
var enhancedTypeRef = property.returnTypeRef
property.getter.transform<FirDeclaration, Any?>(this, enhancedTypeRef)
if (property.returnTypeRef is FirImplicitTypeRef) {
storeVariableReturnType(property)
enhancedTypeRef = property.returnTypeRef
}
property.setter?.let {
it.transform<FirDeclaration, Any?>(this, enhancedTypeRef)
it.valueParameters[0].transformReturnTypeRef(StoreType, enhancedTypeRef)
+12
View File
@@ -0,0 +1,12 @@
val x get() = 1
val y: Int get() = 1
val z = 1
get() = field
val w: Int get(): Int = 1
interface Some {
val bar: Int get() = 1
}
@@ -0,0 +1,24 @@
FILE: typeFromGetter.kt
public final val x: R|kotlin/Int|
public get(): R|kotlin/Int| {
^ Int(1)
}
public final val y: R|kotlin/Int|
public get(): R|kotlin/Int| {
^ Int(1)
}
public final val z: R|kotlin/Int| = Int(1)
public get(): R|kotlin/Int| {
^ F|/z|
}
public final val w: R|kotlin/Int|
public get(): R|kotlin/Int| {
^ Int(1)
}
public abstract interface Some : R|kotlin/Any| {
public open val bar: R|kotlin/Int|
public get(): R|kotlin/Int| {
^ Int(1)
}
}
@@ -144,6 +144,11 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase {
runTest("compiler/fir/resolve/testData/resolve/typeAliasWithGeneric.kt");
}
@TestMetadata("typeFromGetter.kt")
public void testTypeFromGetter() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/typeFromGetter.kt");
}
@TestMetadata("typeParameterInPropertyReceiver.kt")
public void testTypeParameterInPropertyReceiver() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/typeParameterInPropertyReceiver.kt");