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