FIR resolve: integrate receiverExpression inside ReceiverValue

This commit is contained in:
Mikhail Glukhikh
2019-08-29 16:21:21 +03:00
parent 0962755fde
commit 8bb539ce19
3 changed files with 28 additions and 27 deletions
@@ -11,13 +11,10 @@ import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirThisReceiverExpressionImpl
import org.jetbrains.kotlin.fir.references.FirImplicitThisReference
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.types.FirTypeProjection
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtomMarker
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
@@ -68,19 +65,11 @@ class Candidate(
fun dispatchReceiverExpression(): FirExpression = when (explicitReceiverKind) {
ExplicitReceiverKind.DISPATCH_RECEIVER, ExplicitReceiverKind.BOTH_RECEIVERS -> callInfo.explicitReceiver!!
else -> dispatchReceiverValue?.let {
FirThisReceiverExpressionImpl(null, FirImplicitThisReference(it.klassSymbol)).apply {
typeRef = FirResolvedTypeRefImpl(null, it.type)
}
} ?: FirNoReceiverExpression
else -> dispatchReceiverValue?.receiverExpression ?: FirNoReceiverExpression
}
fun extensionReceiverExpression(): FirExpression = when (explicitReceiverKind) {
ExplicitReceiverKind.EXTENSION_RECEIVER, ExplicitReceiverKind.BOTH_RECEIVERS -> callInfo.explicitReceiver!!
else -> implicitExtensionReceiverValue?.let {
FirThisReceiverExpressionImpl(null, FirImplicitThisReference(it.boundSymbol)).apply {
typeRef = FirResolvedTypeRefImpl(null, it.type)
}
} ?: FirNoReceiverExpression
else -> implicitExtensionReceiverValue?.receiverExpression ?: FirNoReceiverExpression
}
}
@@ -8,6 +8,8 @@ package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.classId
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirThisReceiverExpressionImpl
import org.jetbrains.kotlin.fir.references.FirImplicitThisReference
import org.jetbrains.kotlin.fir.renderWithType
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.ScopeSession
@@ -18,20 +20,30 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassTypeImpl
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
interface ReceiverValue {
val type: ConeKotlinType
val receiverExpression: FirExpression
fun scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirScope? =
type.scope(useSiteSession, scopeSession)
}
private fun receiverExpression(symbol: AbstractFirBasedSymbol<*>, type: ConeKotlinType): FirExpression =
FirThisReceiverExpressionImpl(null, FirImplicitThisReference(symbol)).apply {
typeRef = FirResolvedTypeRefImpl(null, type)
}
class ClassDispatchReceiverValue(val klassSymbol: FirClassSymbol) : ReceiverValue {
override val type: ConeKotlinType = ConeClassTypeImpl(
klassSymbol.toLookupTag(),
klassSymbol.fir.typeParameters.map { ConeStarProjection }.toTypedArray(),
isNullable = false
)
override val receiverExpression: FirExpression = receiverExpression(klassSymbol, type)
}
class ExpressionReceiverValue(
@@ -41,6 +53,9 @@ class ExpressionReceiverValue(
override val type: ConeKotlinType
get() = typeProvider(explicitReceiverExpression)?.coneTypeSafe()
?: ConeKotlinErrorType("No type calculated for: ${explicitReceiverExpression.renderWithType()}") // TODO: assert here
override val receiverExpression: FirExpression
get() = explicitReceiverExpression
}
abstract class ImplicitReceiverValue<S : AbstractFirBasedSymbol<*>>(
@@ -52,6 +67,8 @@ abstract class ImplicitReceiverValue<S : AbstractFirBasedSymbol<*>>(
val implicitScope: FirScope? = type.scope(useSiteSession, scopeSession)
override fun scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirScope? = implicitScope
override val receiverExpression: FirExpression = receiverExpression(boundSymbol, type)
}
class ImplicitDispatchReceiverValue(
@@ -60,8 +60,8 @@ internal sealed class CheckReceivers : ResolutionStage() {
return this == DISPATCH_RECEIVER || this == BOTH_RECEIVERS
}
override fun Candidate.getReceiverValue(): ReceiverValue? {
return dispatchReceiverValue
override fun Candidate.getReceiverType(): ConeKotlinType? {
return dispatchReceiverValue?.type
}
}
@@ -74,35 +74,30 @@ internal sealed class CheckReceivers : ResolutionStage() {
return this == EXTENSION_RECEIVER || this == BOTH_RECEIVERS
}
override fun Candidate.getReceiverValue(): ReceiverValue? {
override fun Candidate.getReceiverType(): ConeKotlinType? {
val callableSymbol = symbol as? FirCallableSymbol<*> ?: return null
val callable = callableSymbol.fir
val type = (callable.receiverTypeRef as FirResolvedTypeRef?)?.type ?: return null
return object : ReceiverValue {
override val type: ConeKotlinType
get() = type
}
return (callable.receiverTypeRef as FirResolvedTypeRef?)?.type
}
}
abstract fun Candidate.getReceiverValue(): ReceiverValue?
abstract fun Candidate.getReceiverType(): ConeKotlinType?
abstract fun ExplicitReceiverKind.shouldBeCheckedAgainstExplicit(): Boolean
abstract fun ExplicitReceiverKind.shouldBeCheckedAgainstImplicit(): Boolean
override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
val expectedReceiverParameterValue = candidate.getReceiverValue()
val expectedReceiverType = candidate.getReceiverType()
val explicitReceiverExpression = callInfo.explicitReceiver
val explicitReceiverKind = candidate.explicitReceiverKind
if (expectedReceiverParameterValue != null) {
if (expectedReceiverType != null) {
if (explicitReceiverExpression != null && explicitReceiverKind.shouldBeCheckedAgainstExplicit()) {
resolveArgumentExpression(
candidate.csBuilder,
argument = explicitReceiverExpression,
expectedType = candidate.substitutor.substituteOrSelf(expectedReceiverParameterValue.type),
expectedType = candidate.substitutor.substituteOrSelf(expectedReceiverType),
expectedTypeRef = explicitReceiverExpression.typeRef,
sink = sink,
isReceiver = true,
@@ -117,7 +112,7 @@ internal sealed class CheckReceivers : ResolutionStage() {
resolvePlainArgumentType(
candidate.csBuilder,
argumentType = argumentExtensionReceiverValue.type,
expectedType = candidate.substitutor.substituteOrSelf(expectedReceiverParameterValue.type),
expectedType = candidate.substitutor.substituteOrSelf(expectedReceiverType.type),
sink = sink,
isReceiver = true,
isSafeCall = callInfo.isSafeCall