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()
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val functionCall = if (needTransformArguments) {
|
||||
functionCall.transformExplicitReceiver(transformer, ResolutionMode.ContextIndependent)
|
||||
functionCall.transformExplicitReceiver()
|
||||
.also {
|
||||
dataFlowAnalyzer.enterQualifiedAccessExpression()
|
||||
functionCall.argumentList.transformArguments(transformer, ResolutionMode.ContextDependent)
|
||||
@@ -108,6 +108,20 @@ class FirCallResolver(
|
||||
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(
|
||||
val info: CallInfo, val applicability: CandidateApplicability, val candidates: Collection<Candidate>,
|
||||
)
|
||||
@@ -161,7 +175,7 @@ class FirCallResolver(
|
||||
qualifiedResolver.initProcessingQualifiedAccess(callee)
|
||||
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val qualifiedAccess = qualifiedAccess.transformExplicitReceiver(transformer, ResolutionMode.ContextIndependent)
|
||||
val qualifiedAccess = qualifiedAccess.transformExplicitReceiver<FirQualifiedAccess>()
|
||||
qualifiedResolver.replacedQualifier(qualifiedAccess)?.let { 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.resolve.*
|
||||
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.inference.FirStubInferenceSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.InvocationKindTransformer
|
||||
@@ -85,46 +84,7 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
||||
qualifiedAccessExpression
|
||||
}
|
||||
is FirSuperReference -> {
|
||||
val labelName = callee.labelName
|
||||
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
|
||||
transformSuperReceiver(callee, qualifiedAccessExpression)
|
||||
}
|
||||
is FirDelegateFieldReference -> {
|
||||
val delegateFieldSymbol = callee.resolvedSymbol
|
||||
@@ -164,6 +124,52 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
||||
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 {
|
||||
return true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user