From 8bb539ce19d7cb6dcf6d0ef256c9ddacb1c1b241 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Thu, 29 Aug 2019 16:21:21 +0300 Subject: [PATCH] FIR resolve: integrate receiverExpression inside ReceiverValue --- .../kotlin/fir/resolve/calls/Candidate.kt | 15 ++---------- .../kotlin/fir/resolve/calls/FirReceivers.kt | 17 ++++++++++++++ .../kotlin/fir/resolve/calls/ResolverParts.kt | 23 ++++++++----------- 3 files changed, 28 insertions(+), 27 deletions(-) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt index ff7c793fa09..fbc7939f46f 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt @@ -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 } } \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirReceivers.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirReceivers.kt index 9d051c9b3a2..4ac7553ce96 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirReceivers.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirReceivers.kt @@ -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>( @@ -52,6 +67,8 @@ abstract class ImplicitReceiverValue>( 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( diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt index 512b8a68856..f8f802251d3 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt @@ -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