FIR resolve: perform inference completion for property access
This commit is contained in:
committed by
Mikhail Glukhikh
parent
99680a2ad7
commit
1222449dc8
+21
-5
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirResolvedQualifierImpl
|
||||
import org.jetbrains.kotlin.fir.references.FirBackingFieldReferenceImpl
|
||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReferenceImpl
|
||||
import org.jetbrains.kotlin.fir.references.FirSimpleNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.*
|
||||
@@ -26,6 +27,8 @@ import org.jetbrains.kotlin.fir.scopes.impl.FirTopLevelDeclaredMemberScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType
|
||||
import org.jetbrains.kotlin.fir.symbols.*
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirBackingFieldSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.*
|
||||
@@ -386,6 +389,7 @@ open class FirBodyResolveTransformer(
|
||||
val types = if (labelName == null) labels.values() else labels[Name.identifier(labelName)]
|
||||
val type = types.lastOrNull() ?: ConeKotlinErrorType("Unresolved this@$labelName")
|
||||
qualifiedAccessExpression.resultType = FirResolvedTypeRefImpl(session, null, type, emptyList())
|
||||
return qualifiedAccessExpression.compose()
|
||||
}
|
||||
is FirSuperReference -> {
|
||||
if (callee.superTypeRef is FirResolvedTypeRef) {
|
||||
@@ -397,14 +401,23 @@ open class FirBodyResolveTransformer(
|
||||
qualifiedAccessExpression.resultType = superTypeRef
|
||||
callee.replaceSuperTypeRef(superTypeRef)
|
||||
}
|
||||
return qualifiedAccessExpression.compose()
|
||||
}
|
||||
is FirResolvedCallableReference -> {
|
||||
if (qualifiedAccessExpression.typeRef !is FirResolvedTypeRef) {
|
||||
storeTypeFromCallee(qualifiedAccessExpression)
|
||||
}
|
||||
return qualifiedAccessExpression.compose()
|
||||
}
|
||||
}
|
||||
return transformCallee(qualifiedAccessExpression).compose()
|
||||
val transformedCallee = transformCallee(qualifiedAccessExpression)
|
||||
// NB: here we can get raw expression because of dropped qualifiers (see transform callee),
|
||||
// so candidate existence must be checked before calling completion
|
||||
return if (transformedCallee is FirQualifiedAccessExpression && transformedCallee.candidate() != null) {
|
||||
completeTypeInference(transformedCallee, data as? FirTypeRef).compose()
|
||||
} else {
|
||||
transformedCallee.compose()
|
||||
}
|
||||
}
|
||||
|
||||
override fun transformVariableAssignment(
|
||||
@@ -774,10 +787,13 @@ open class FirBodyResolveTransformer(
|
||||
}
|
||||
candidates.size == 1 -> {
|
||||
val candidate = candidates.single()
|
||||
if (candidate.symbol is FirBackingFieldSymbol) {
|
||||
FirBackingFieldReferenceImpl(firSession, psi, candidate.symbol)
|
||||
} else {
|
||||
FirNamedReferenceWithCandidate(firSession, psi, name, candidate)
|
||||
val coneSymbol = candidate.symbol
|
||||
when {
|
||||
coneSymbol is FirBackingFieldSymbol -> FirBackingFieldReferenceImpl(firSession, psi, coneSymbol)
|
||||
coneSymbol is FirVariableSymbol &&
|
||||
(coneSymbol !is FirPropertySymbol || coneSymbol.firUnsafe<FirMemberDeclaration>().typeParameters.isEmpty()) ->
|
||||
FirResolvedCallableReferenceImpl(firSession, psi, name, coneSymbol)
|
||||
else -> FirNamedReferenceWithCandidate(firSession, psi, name, candidate)
|
||||
}
|
||||
}
|
||||
else -> FirErrorNamedReference(
|
||||
|
||||
+28
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReferenceImpl
|
||||
@@ -33,6 +34,33 @@ class FirCallCompleterTransformer(
|
||||
private val typeCalculator: ReturnTypeCalculator
|
||||
) : FirAbstractTreeTransformer() {
|
||||
|
||||
override fun transformQualifiedAccessExpression(
|
||||
qualifiedAccessExpression: FirQualifiedAccessExpression,
|
||||
data: Nothing?
|
||||
): CompositeTransformResult<FirStatement> {
|
||||
val calleeReference =
|
||||
qualifiedAccessExpression.calleeReference as? FirNamedReferenceWithCandidate ?: return qualifiedAccessExpression.compose()
|
||||
calleeReference.candidate.substitutor
|
||||
|
||||
val typeRef = typeCalculator.tryCalculateReturnType(calleeReference.coneSymbol.firUnsafe())
|
||||
|
||||
val initialType = calleeReference.candidate.substitutor.substituteOrNull(typeRef.type)
|
||||
val finalType = finalSubstitutor.substituteOrNull(initialType)
|
||||
|
||||
val resultType = typeRef.withReplacedConeType(session, finalType)
|
||||
qualifiedAccessExpression.replaceTypeRef(resultType)
|
||||
|
||||
return qualifiedAccessExpression.transformCalleeReference(
|
||||
StoreCalleeReference,
|
||||
FirResolvedCallableReferenceImpl(
|
||||
calleeReference.session,
|
||||
calleeReference.psi,
|
||||
calleeReference.name,
|
||||
calleeReference.coneSymbol
|
||||
)
|
||||
).compose()
|
||||
}
|
||||
|
||||
override fun transformVariableAssignment(
|
||||
variableAssignment: FirVariableAssignment,
|
||||
data: Nothing?
|
||||
|
||||
@@ -24,6 +24,5 @@ FILE fqName:<root> fileName:/classReference.kt
|
||||
GET_OBJECT 'CLASS CLASS name:A modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit
|
||||
GET_CLASS type=kotlin.reflect.KClass<<root>.A>
|
||||
CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in <root>.A' type=<root>.A origin=null
|
||||
ERROR_CALL 'No getter found for R|kotlin/jvm/java|' type=java.lang.Class<T of <uninitialized parent>>
|
||||
ERROR_CALL 'No getter found for R|kotlin/jvm/java|' type=java.lang.Class<T of <uninitialized parent>>
|
||||
|
||||
ERROR_CALL 'No getter found for R|kotlin/jvm/java|' type=java.lang.Class<<root>.A>
|
||||
ERROR_CALL 'No getter found for R|kotlin/jvm/java|' type=java.lang.Class<<root>.A>
|
||||
|
||||
@@ -161,12 +161,11 @@ FILE fqName:<root> fileName:/genericPropertyRef.kt
|
||||
SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:value2 type:kotlin.Any? visibility:public [static] ' type=kotlin.Any? origin=null
|
||||
value: GET_VAR 'value: T of <uninitialized parent> declared in <root>.<set-bar>' type=T of <uninitialized parent> origin=null
|
||||
PROPERTY name:barRef visibility:public modality:FINAL [val]
|
||||
FIELD PROPERTY_BACKING_FIELD name:barRef type:T of <uninitialized parent> visibility:public [final,static]
|
||||
FIELD PROPERTY_BACKING_FIELD name:barRef type:kotlin.String.Companion visibility:public [final,static]
|
||||
EXPRESSION_BODY
|
||||
CALL 'public final fun <get-bar> (): T of <uninitialized parent> declared in <root>' type=T of <uninitialized parent> origin=null
|
||||
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-barRef> visibility:public modality:FINAL <> () returnType:T of <uninitialized parent>
|
||||
CALL 'public final fun <get-bar> (): T of <uninitialized parent> declared in <root>' type=kotlin.String.Companion origin=null
|
||||
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-barRef> visibility:public modality:FINAL <> () returnType:kotlin.String.Companion
|
||||
correspondingProperty: PROPERTY name:barRef visibility:public modality:FINAL [val]
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun <get-barRef> (): T of <uninitialized parent> declared in <root>'
|
||||
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:barRef type:T of <uninitialized parent> visibility:public [final,static] ' type=T of <uninitialized parent> origin=null
|
||||
|
||||
RETURN type=kotlin.Nothing from='public final fun <get-barRef> (): kotlin.String.Companion declared in <root>'
|
||||
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:barRef type:kotlin.String.Companion visibility:public [final,static] ' type=kotlin.String.Companion origin=null
|
||||
|
||||
@@ -22,5 +22,4 @@ FILE fqName:<root> fileName:/objectClassReference.kt
|
||||
BLOCK_BODY
|
||||
GET_CLASS type=kotlin.reflect.KClass<<root>.A>
|
||||
GET_OBJECT 'CLASS OBJECT name:A modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.A
|
||||
ERROR_CALL 'No getter found for R|kotlin/jvm/java|' type=java.lang.Class<T of <uninitialized parent>>
|
||||
|
||||
ERROR_CALL 'No getter found for R|kotlin/jvm/java|' type=java.lang.Class<<root>.A>
|
||||
|
||||
@@ -208,7 +208,7 @@ FILE fqName:<root> fileName:/useImportedMember.kt
|
||||
BRANCH
|
||||
if: CALL 'public final fun not (): kotlin.Boolean declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ
|
||||
$this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ
|
||||
arg0: CALL 'public final fun <get-g2> (): T of <uninitialized parent> declared in <root>.C' type=T of <uninitialized parent> origin=null
|
||||
arg0: CALL 'public final fun <get-g2> (): T of <uninitialized parent> declared in <root>.C' type=kotlin.String origin=null
|
||||
$this: CONST String type=kotlin.String value="8"
|
||||
arg1: CONST String type=kotlin.String value="8"
|
||||
then: RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in <root>'
|
||||
@@ -225,7 +225,7 @@ FILE fqName:<root> fileName:/useImportedMember.kt
|
||||
BRANCH
|
||||
if: CALL 'public final fun not (): kotlin.Boolean declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ
|
||||
$this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ
|
||||
arg0: CALL 'public final fun <get-fromClass> (): T of <uninitialized parent> declared in <root>.BaseClass' type=T of <uninitialized parent> origin=null
|
||||
arg0: CALL 'public final fun <get-fromClass> (): T of <uninitialized parent> declared in <root>.BaseClass' type=kotlin.String origin=null
|
||||
$this: CONST String type=kotlin.String value="10"
|
||||
arg1: CONST String type=kotlin.String value="10"
|
||||
then: RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in <root>'
|
||||
|
||||
Reference in New Issue
Block a user