[FIR] Implement super resolve as a particular tower resolver case
This commit is contained in:
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.references.FirSuperReference
|
||||
import org.jetbrains.kotlin.fir.references.FirThisReference
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ConeInferenceContext
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.isSuperReferenceExpression
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.FirUnresolvedNameError
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.AbstractConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
|
||||
@@ -371,8 +372,10 @@ fun <T : FirResolvable> BodyResolveComponents.typeFromCallee(access: T): FirReso
|
||||
val receiverResultType = explicitReceiver.resultType
|
||||
if (receiverResultType is FirResolvedTypeRef) {
|
||||
receiverResultType.type.isNullable
|
||||
} else {
|
||||
} else if (receiverResultType !is FirComposedSuperTypeRef || !explicitReceiver.isSuperReferenceExpression()){
|
||||
throw AssertionError("Receiver ${explicitReceiver.render()} type is unresolved: ${receiverResultType.render()}")
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
|
||||
+35
-3
@@ -13,17 +13,20 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedImportImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.isCompanion
|
||||
import org.jetbrains.kotlin.fir.declarations.isInner
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
||||
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
|
||||
import org.jetbrains.kotlin.fir.resolve.scope
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirExplicitSimpleImportingScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirStaticScope
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeIntegerLiteralType
|
||||
import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
@@ -348,6 +351,27 @@ class FirTowerResolver(
|
||||
return collector
|
||||
}
|
||||
|
||||
private fun runResolverForSuperReceiver(
|
||||
info: CallInfo,
|
||||
collector: CandidateCollector,
|
||||
superTypeRef: FirTypeRef,
|
||||
manager: TowerResolveManager
|
||||
): CandidateCollector {
|
||||
val scope = when (superTypeRef) {
|
||||
is FirResolvedTypeRef -> superTypeRef.type.scope(session, components.scopeSession)
|
||||
is FirComposedSuperTypeRef -> FirCompositeScope(
|
||||
superTypeRef.superTypeRefs.mapNotNullTo(mutableListOf()) { it.type.scope(session, components.scopeSession) }
|
||||
)
|
||||
else -> null
|
||||
} ?: return collector
|
||||
manager.processLevel(
|
||||
ScopeTowerLevel(
|
||||
session, components, scope
|
||||
), info, TowerGroup.Member, explicitReceiverKind = ExplicitReceiverKind.DISPATCH_RECEIVER
|
||||
)
|
||||
return collector
|
||||
}
|
||||
|
||||
internal fun enqueueResolverForInvoke(
|
||||
info: CallInfo,
|
||||
invokeReceiverValue: ExpressionReceiverValue,
|
||||
@@ -459,7 +483,15 @@ class FirTowerResolver(
|
||||
return when (val receiver = info.explicitReceiver) {
|
||||
is FirResolvedQualifier -> runResolverForQualifierReceiver(info, collector, receiver, manager)
|
||||
null -> runResolverForNoReceiver(info, collector, manager)
|
||||
else -> runResolverForExpressionReceiver(info, collector, receiver, manager)
|
||||
else -> {
|
||||
if (receiver is FirQualifiedAccessExpression) {
|
||||
val calleeReference = receiver.calleeReference
|
||||
if (calleeReference is FirSuperReference) {
|
||||
return runResolverForSuperReceiver(info, collector, receiver.typeRef, manager)
|
||||
}
|
||||
}
|
||||
runResolverForExpressionReceiver(info, collector, receiver, manager)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,10 @@ package org.jetbrains.kotlin.fir.resolve.calls
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
@@ -33,6 +36,13 @@ abstract class ResolutionStage {
|
||||
|
||||
abstract class CheckerStage : ResolutionStage()
|
||||
|
||||
internal fun FirExpression.isSuperReferenceExpression(): Boolean {
|
||||
return if (this is FirQualifiedAccessExpression) {
|
||||
val calleeReference = calleeReference
|
||||
calleeReference is FirSuperReference
|
||||
} else false
|
||||
}
|
||||
|
||||
internal object CheckExplicitReceiverConsistency : ResolutionStage() {
|
||||
override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
|
||||
val receiverKind = candidate.explicitReceiverKind
|
||||
@@ -40,7 +50,7 @@ internal object CheckExplicitReceiverConsistency : ResolutionStage() {
|
||||
// TODO: add invoke cases
|
||||
when (receiverKind) {
|
||||
NO_EXPLICIT_RECEIVER -> {
|
||||
if (explicitReceiver != null && explicitReceiver !is FirResolvedQualifier) {
|
||||
if (explicitReceiver != null && explicitReceiver !is FirResolvedQualifier && !explicitReceiver.isSuperReferenceExpression()) {
|
||||
return sink.yieldApplicability(CandidateApplicability.WRONG_RECEIVER)
|
||||
}
|
||||
}
|
||||
@@ -106,7 +116,10 @@ internal sealed class CheckReceivers : ResolutionStage() {
|
||||
val explicitReceiverKind = candidate.explicitReceiverKind
|
||||
|
||||
if (expectedReceiverType != null) {
|
||||
if (explicitReceiverExpression != null && explicitReceiverKind.shouldBeCheckedAgainstExplicit()) {
|
||||
if (explicitReceiverExpression != null &&
|
||||
explicitReceiverKind.shouldBeCheckedAgainstExplicit() &&
|
||||
!explicitReceiverExpression.isSuperReferenceExpression()
|
||||
) {
|
||||
candidate.resolveArgumentExpression(
|
||||
candidate.csBuilder,
|
||||
argument = explicitReceiverExpression,
|
||||
|
||||
+18
-7
@@ -89,13 +89,24 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) :
|
||||
qualifiedAccessExpression.resultType = callee.superTypeRef
|
||||
}
|
||||
else -> {
|
||||
val superTypeRefFromStack = implicitReceiverStack.lastDispatchReceiver()
|
||||
?.boundSymbol?.phasedFir?.superTypeRefs?.firstOrNull()
|
||||
?: FirErrorTypeRefImpl(
|
||||
qualifiedAccessExpression.source, FirSimpleDiagnostic("No super type", DiagnosticKind.NoSupertype)
|
||||
)
|
||||
qualifiedAccessExpression.resultType = superTypeRefFromStack
|
||||
callee.replaceSuperTypeRef(superTypeRefFromStack)
|
||||
val superTypeRefs = implicitReceiverStack.lastDispatchReceiver()?.boundSymbol?.phasedFir?.superTypeRefs
|
||||
val resultType = when {
|
||||
superTypeRefs?.isNotEmpty() != true -> {
|
||||
FirErrorTypeRefImpl(
|
||||
qualifiedAccessExpression.source, FirSimpleDiagnostic("No super type", DiagnosticKind.NoSupertype)
|
||||
)
|
||||
}
|
||||
superTypeRefs.size == 1 -> {
|
||||
superTypeRefs.single()
|
||||
}
|
||||
else -> {
|
||||
FirComposedSuperTypeRefImpl(qualifiedAccessExpression.source).apply {
|
||||
this.superTypeRefs += superTypeRefs.map { it as FirResolvedTypeRef }
|
||||
}
|
||||
}
|
||||
}
|
||||
qualifiedAccessExpression.resultType = resultType
|
||||
callee.replaceSuperTypeRef(resultType)
|
||||
}
|
||||
}
|
||||
qualifiedAccessExpression
|
||||
|
||||
@@ -9,8 +9,8 @@ open class B {
|
||||
|
||||
class C : A, B() {
|
||||
override fun foo() {
|
||||
super.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
super.foo()
|
||||
|
||||
super.bar() // should be ambiguity
|
||||
super.<!AMBIGUITY!>bar<!>() // should be ambiguity (NB: really we should have overridden bar in C)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,8 +22,8 @@ FILE: incorrectSuperCall.kt
|
||||
}
|
||||
|
||||
public final override fun foo(): R|kotlin/Unit| {
|
||||
super<R|A|>.<Unresolved name: foo>#()
|
||||
super<R|A|>.R|/A.bar|()
|
||||
super<R|A|R|B|>.R|/B.foo|()
|
||||
super<R|A|R|B|>.<Ambiguity: bar, [/A.bar, /B.bar]>#()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -268,6 +268,8 @@ class FirResolveBench(val withProgress: Boolean) {
|
||||
visitTypeRef(implicitTypeRef)
|
||||
}
|
||||
|
||||
override fun visitComposedSuperTypeRef(composedSuperTypeRef: FirComposedSuperTypeRef) {}
|
||||
|
||||
override fun visitResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef) {
|
||||
resolvedTypes++
|
||||
val type = resolvedTypeRef.type
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.types
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirPureAbstractElement
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||
import org.jetbrains.kotlin.fir.visitors.*
|
||||
|
||||
/*
|
||||
* This file was generated automatically
|
||||
* DO NOT MODIFY IT MANUALLY
|
||||
*/
|
||||
|
||||
abstract class FirComposedSuperTypeRef : FirPureAbstractElement(), FirTypeRef {
|
||||
abstract override val source: FirSourceElement?
|
||||
abstract override val annotations: List<FirAnnotationCall>
|
||||
abstract val superTypeRefs: List<FirResolvedTypeRef>
|
||||
|
||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitComposedSuperTypeRef(this, data)
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.types.impl
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||
import org.jetbrains.kotlin.fir.impl.FirAbstractAnnotatedElement
|
||||
import org.jetbrains.kotlin.fir.types.FirComposedSuperTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.visitors.*
|
||||
|
||||
/*
|
||||
* This file was generated automatically
|
||||
* DO NOT MODIFY IT MANUALLY
|
||||
*/
|
||||
|
||||
class FirComposedSuperTypeRefImpl(
|
||||
override val source: FirSourceElement?
|
||||
) : FirComposedSuperTypeRef(), FirAbstractAnnotatedElement {
|
||||
override val annotations: MutableList<FirAnnotationCall> = mutableListOf()
|
||||
override val superTypeRefs: MutableList<FirResolvedTypeRef> = mutableListOf()
|
||||
|
||||
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
|
||||
annotations.forEach { it.accept(visitor, data) }
|
||||
superTypeRefs.forEach { it.accept(visitor, data) }
|
||||
}
|
||||
|
||||
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirComposedSuperTypeRefImpl {
|
||||
annotations.transformInplace(transformer, data)
|
||||
superTypeRefs.transformInplace(transformer, data)
|
||||
return this
|
||||
}
|
||||
}
|
||||
@@ -116,6 +116,7 @@ import org.jetbrains.kotlin.fir.types.FirDynamicTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirFunctionTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedFunctionTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirComposedSuperTypeRef
|
||||
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
|
||||
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
|
||||
|
||||
@@ -568,6 +569,10 @@ abstract class FirTransformer<in D> : FirVisitor<CompositeTransformResult<FirEle
|
||||
return transformElement(implicitTypeRef, data)
|
||||
}
|
||||
|
||||
open fun transformComposedSuperTypeRef(composedSuperTypeRef: FirComposedSuperTypeRef, data: D): CompositeTransformResult<FirTypeRef> {
|
||||
return transformElement(composedSuperTypeRef, data)
|
||||
}
|
||||
|
||||
open fun transformContractDescription(contractDescription: FirContractDescription, data: D): CompositeTransformResult<FirContractDescription> {
|
||||
return transformElement(contractDescription, data)
|
||||
}
|
||||
@@ -1016,6 +1021,10 @@ abstract class FirTransformer<in D> : FirVisitor<CompositeTransformResult<FirEle
|
||||
return transformImplicitTypeRef(implicitTypeRef, data)
|
||||
}
|
||||
|
||||
final override fun visitComposedSuperTypeRef(composedSuperTypeRef: FirComposedSuperTypeRef, data: D): CompositeTransformResult<FirTypeRef> {
|
||||
return transformComposedSuperTypeRef(composedSuperTypeRef, data)
|
||||
}
|
||||
|
||||
final override fun visitContractDescription(contractDescription: FirContractDescription, data: D): CompositeTransformResult<FirContractDescription> {
|
||||
return transformContractDescription(contractDescription, data)
|
||||
}
|
||||
|
||||
@@ -116,6 +116,7 @@ import org.jetbrains.kotlin.fir.types.FirDynamicTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirFunctionTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedFunctionTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirComposedSuperTypeRef
|
||||
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
|
||||
|
||||
/*
|
||||
@@ -346,6 +347,8 @@ abstract class FirVisitor<out R, in D> {
|
||||
|
||||
open fun visitImplicitTypeRef(implicitTypeRef: FirImplicitTypeRef, data: D): R = visitElement(implicitTypeRef, data)
|
||||
|
||||
open fun visitComposedSuperTypeRef(composedSuperTypeRef: FirComposedSuperTypeRef, data: D): R = visitElement(composedSuperTypeRef, data)
|
||||
|
||||
open fun visitContractDescription(contractDescription: FirContractDescription, data: D): R = visitElement(contractDescription, data)
|
||||
|
||||
}
|
||||
|
||||
@@ -116,6 +116,7 @@ import org.jetbrains.kotlin.fir.types.FirDynamicTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirFunctionTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedFunctionTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirComposedSuperTypeRef
|
||||
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
|
||||
|
||||
/*
|
||||
@@ -566,6 +567,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
|
||||
visitElement(implicitTypeRef)
|
||||
}
|
||||
|
||||
open fun visitComposedSuperTypeRef(composedSuperTypeRef: FirComposedSuperTypeRef) {
|
||||
visitElement(composedSuperTypeRef)
|
||||
}
|
||||
|
||||
open fun visitContractDescription(contractDescription: FirContractDescription) {
|
||||
visitElement(contractDescription)
|
||||
}
|
||||
@@ -1014,6 +1019,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
|
||||
visitImplicitTypeRef(implicitTypeRef)
|
||||
}
|
||||
|
||||
final override fun visitComposedSuperTypeRef(composedSuperTypeRef: FirComposedSuperTypeRef, data: Nothing?) {
|
||||
visitComposedSuperTypeRef(composedSuperTypeRef)
|
||||
}
|
||||
|
||||
final override fun visitContractDescription(contractDescription: FirContractDescription, data: Nothing?) {
|
||||
visitContractDescription(contractDescription)
|
||||
}
|
||||
|
||||
+1
@@ -137,6 +137,7 @@ object FirTreeBuilder : AbstractFirTreeBuilder() {
|
||||
val functionTypeRef = element("FunctionTypeRef", TypeRef, typeRefWithNullability)
|
||||
val resolvedFunctionTypeRef = element("ResolvedFunctionTypeRef", TypeRef, resolvedTypeRef, functionTypeRef)
|
||||
val implicitTypeRef = element("ImplicitTypeRef", TypeRef, typeRef)
|
||||
val composedSuperTypeRef = element("ComposedSuperTypeRef", TypeRef, typeRef)
|
||||
|
||||
val contractDescription = element("ContractDescription", Contracts)
|
||||
}
|
||||
+2
@@ -513,6 +513,8 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
defaultEmptyList("annotations")
|
||||
}
|
||||
|
||||
impl(composedSuperTypeRef)
|
||||
|
||||
impl(reference, "FirStubReference") {
|
||||
default("source") {
|
||||
value = "null"
|
||||
|
||||
+4
@@ -521,6 +521,10 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
|
||||
+returnTypeRef
|
||||
}
|
||||
|
||||
composedSuperTypeRef.configure {
|
||||
+fieldList("superTypeRefs", resolvedTypeRef)
|
||||
}
|
||||
|
||||
thisReceiverExpression.configure {
|
||||
+field("calleeReference", thisReference)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user