[FIR] Implement super resolve as a particular tower resolver case

This commit is contained in:
Mikhail Glukhikh
2020-01-29 12:41:45 +03:00
parent ee020ef290
commit 71b0840ef9
42 changed files with 211 additions and 71 deletions
@@ -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
@@ -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,
@@ -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)
}
@@ -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)
}
@@ -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)
}
@@ -513,6 +513,8 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
defaultEmptyList("annotations")
}
impl(composedSuperTypeRef)
impl(reference, "FirStubReference") {
default("source") {
value = "null"
@@ -521,6 +521,10 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
+returnTypeRef
}
composedSuperTypeRef.configure {
+fieldList("superTypeRefs", resolvedTypeRef)
}
thisReceiverExpression.configure {
+field("calleeReference", thisReference)
}