FIR: Handle super-receiver case in a special way
Before this change, it was resolved independently of containg call But in fact, the type of `super` depends on the name of the callee (see KT-39599 and KT-39070)
This commit is contained in:
@@ -66,7 +66,7 @@ class FirCallResolver(
|
|||||||
qualifiedResolver.reset()
|
qualifiedResolver.reset()
|
||||||
@Suppress("NAME_SHADOWING")
|
@Suppress("NAME_SHADOWING")
|
||||||
val functionCall = if (needTransformArguments) {
|
val functionCall = if (needTransformArguments) {
|
||||||
functionCall.transformExplicitReceiver(transformer, ResolutionMode.ContextIndependent)
|
functionCall.transformExplicitReceiver()
|
||||||
.also {
|
.also {
|
||||||
dataFlowAnalyzer.enterQualifiedAccessExpression()
|
dataFlowAnalyzer.enterQualifiedAccessExpression()
|
||||||
functionCall.argumentList.transformArguments(transformer, ResolutionMode.ContextDependent)
|
functionCall.argumentList.transformArguments(transformer, ResolutionMode.ContextDependent)
|
||||||
@@ -108,6 +108,20 @@ class FirCallResolver(
|
|||||||
return resultFunctionCall
|
return resultFunctionCall
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private inline fun <reified Q : FirQualifiedAccess> Q.transformExplicitReceiver(): Q {
|
||||||
|
val explicitReceiver =
|
||||||
|
explicitReceiver as? FirQualifiedAccessExpression
|
||||||
|
?: return transformExplicitReceiver(transformer, ResolutionMode.ContextIndependent) as Q
|
||||||
|
|
||||||
|
val callee =
|
||||||
|
explicitReceiver.calleeReference as? FirSuperReference
|
||||||
|
?: return transformExplicitReceiver(transformer, ResolutionMode.ContextIndependent) as Q
|
||||||
|
|
||||||
|
transformer.transformSuperReceiver(callee, explicitReceiver)
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
private data class ResolutionResult(
|
private data class ResolutionResult(
|
||||||
val info: CallInfo, val applicability: CandidateApplicability, val candidates: Collection<Candidate>,
|
val info: CallInfo, val applicability: CandidateApplicability, val candidates: Collection<Candidate>,
|
||||||
)
|
)
|
||||||
@@ -161,7 +175,7 @@ class FirCallResolver(
|
|||||||
qualifiedResolver.initProcessingQualifiedAccess(callee)
|
qualifiedResolver.initProcessingQualifiedAccess(callee)
|
||||||
|
|
||||||
@Suppress("NAME_SHADOWING")
|
@Suppress("NAME_SHADOWING")
|
||||||
val qualifiedAccess = qualifiedAccess.transformExplicitReceiver(transformer, ResolutionMode.ContextIndependent)
|
val qualifiedAccess = qualifiedAccess.transformExplicitReceiver<FirQualifiedAccess>()
|
||||||
qualifiedResolver.replacedQualifier(qualifiedAccess)?.let { resolvedQualifierPart ->
|
qualifiedResolver.replacedQualifier(qualifiedAccess)?.let { resolvedQualifierPart ->
|
||||||
return resolvedQualifierPart
|
return resolvedQualifierPart
|
||||||
}
|
}
|
||||||
|
|||||||
+47
-41
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.fir.references.builder.buildSimpleNamedReference
|
|||||||
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
|
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
|
||||||
import org.jetbrains.kotlin.fir.resolve.*
|
import org.jetbrains.kotlin.fir.resolve.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.*
|
import org.jetbrains.kotlin.fir.resolve.calls.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.candidate
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.*
|
import org.jetbrains.kotlin.fir.resolve.diagnostics.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.inference.FirStubInferenceSession
|
import org.jetbrains.kotlin.fir.resolve.inference.FirStubInferenceSession
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.InvocationKindTransformer
|
import org.jetbrains.kotlin.fir.resolve.transformers.InvocationKindTransformer
|
||||||
@@ -85,46 +84,7 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
|||||||
qualifiedAccessExpression
|
qualifiedAccessExpression
|
||||||
}
|
}
|
||||||
is FirSuperReference -> {
|
is FirSuperReference -> {
|
||||||
val labelName = callee.labelName
|
transformSuperReceiver(callee, qualifiedAccessExpression)
|
||||||
val implicitReceiver =
|
|
||||||
if (labelName != null) implicitReceiverStack[labelName] as? ImplicitDispatchReceiverValue
|
|
||||||
else implicitReceiverStack.lastDispatchReceiver()
|
|
||||||
implicitReceiver?.receiverExpression?.let {
|
|
||||||
qualifiedAccessExpression.transformDispatchReceiver(StoreReceiver, it)
|
|
||||||
}
|
|
||||||
when (val superTypeRef = callee.superTypeRef) {
|
|
||||||
is FirResolvedTypeRef -> {
|
|
||||||
qualifiedAccessExpression.resultType = superTypeRef
|
|
||||||
}
|
|
||||||
!is FirImplicitTypeRef -> {
|
|
||||||
callee.transformChildren(transformer, ResolutionMode.ContextIndependent)
|
|
||||||
qualifiedAccessExpression.resultType = callee.superTypeRef
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
val superTypeRefs = implicitReceiver?.boundSymbol?.phasedFir?.superTypeRefs
|
|
||||||
val resultType = when {
|
|
||||||
superTypeRefs?.isNotEmpty() != true -> {
|
|
||||||
buildErrorTypeRef {
|
|
||||||
source = qualifiedAccessExpression.source
|
|
||||||
// NB: NOT_A_SUPERTYPE is reported by a separate checker
|
|
||||||
diagnostic = ConeStubDiagnostic(ConeSimpleDiagnostic("No super type", DiagnosticKind.Other))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
superTypeRefs.size == 1 -> {
|
|
||||||
superTypeRefs.single()
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
buildComposedSuperTypeRef {
|
|
||||||
source = qualifiedAccessExpression.source
|
|
||||||
superTypeRefs.mapTo(this.superTypeRefs) { it as FirResolvedTypeRef }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
qualifiedAccessExpression.resultType = resultType
|
|
||||||
callee.replaceSuperTypeRef(resultType)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
qualifiedAccessExpression
|
|
||||||
}
|
}
|
||||||
is FirDelegateFieldReference -> {
|
is FirDelegateFieldReference -> {
|
||||||
val delegateFieldSymbol = callee.resolvedSymbol
|
val delegateFieldSymbol = callee.resolvedSymbol
|
||||||
@@ -164,6 +124,52 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
|||||||
return result.compose()
|
return result.compose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun transformSuperReceiver(
|
||||||
|
superReference: FirSuperReference,
|
||||||
|
superReferenceContainer: FirQualifiedAccessExpression
|
||||||
|
): FirQualifiedAccessExpression {
|
||||||
|
val labelName = superReference.labelName
|
||||||
|
val implicitReceiver =
|
||||||
|
if (labelName != null) implicitReceiverStack[labelName] as? ImplicitDispatchReceiverValue
|
||||||
|
else implicitReceiverStack.lastDispatchReceiver()
|
||||||
|
implicitReceiver?.receiverExpression?.let {
|
||||||
|
superReferenceContainer.transformDispatchReceiver(StoreReceiver, it)
|
||||||
|
}
|
||||||
|
when (val superTypeRef = superReference.superTypeRef) {
|
||||||
|
is FirResolvedTypeRef -> {
|
||||||
|
superReferenceContainer.resultType = superTypeRef
|
||||||
|
}
|
||||||
|
!is FirImplicitTypeRef -> {
|
||||||
|
superReference.transformChildren(transformer, ResolutionMode.ContextIndependent)
|
||||||
|
superReferenceContainer.resultType = superReference.superTypeRef
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
val superTypeRefs = implicitReceiver?.boundSymbol?.phasedFir?.superTypeRefs
|
||||||
|
val resultType = when {
|
||||||
|
superTypeRefs?.isNotEmpty() != true -> {
|
||||||
|
buildErrorTypeRef {
|
||||||
|
source = superReferenceContainer.source
|
||||||
|
// NB: NOT_A_SUPERTYPE is reported by a separate checker
|
||||||
|
diagnostic = ConeStubDiagnostic(ConeSimpleDiagnostic("No super type", DiagnosticKind.Other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
superTypeRefs.size == 1 -> {
|
||||||
|
superTypeRefs.single()
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
buildComposedSuperTypeRef {
|
||||||
|
source = superReferenceContainer.source
|
||||||
|
superTypeRefs.mapTo(this.superTypeRefs) { it as FirResolvedTypeRef }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
superReferenceContainer.resultType = resultType
|
||||||
|
superReference.replaceSuperTypeRef(resultType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return superReferenceContainer
|
||||||
|
}
|
||||||
|
|
||||||
protected open fun FirQualifiedAccessExpression.isAcceptableResolvedQualifiedAccess(): Boolean {
|
protected open fun FirQualifiedAccessExpression.isAcceptableResolvedQualifiedAccess(): Boolean {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user