[FIR] Store expressions of receivers inside candidates instead of ReceiverValue
This is needed because of mutable nature of receiver values: implicit receiver values can be modified because of smartcasts, but in candidate we need to store snapshot of receiver in the form it was at the beginning of the resolution ^KT-58823 Fixed
This commit is contained in:
committed by
Space Team
parent
b564260a33
commit
6409bf2fe8
+4
-4
@@ -447,15 +447,15 @@ internal class KtFirCallResolver(
|
||||
) {
|
||||
// Implicit invoke (e.g., `x()`) will have a different callee symbol (e.g., `x`) than the candidate (e.g., `invoke`).
|
||||
createKtPartiallyAppliedSymbolForImplicitInvoke(
|
||||
candidate.dispatchReceiverValue?.receiverExpression ?: FirNoReceiverExpression,
|
||||
candidate.chosenExtensionReceiverValue?.receiverExpression ?: FirNoReceiverExpression,
|
||||
candidate.dispatchReceiver ?: FirNoReceiverExpression,
|
||||
candidate.chosenExtensionReceiver ?: FirNoReceiverExpression,
|
||||
candidate.explicitReceiverKind
|
||||
)
|
||||
} else {
|
||||
KtPartiallyAppliedSymbol(
|
||||
with(analysisSession) { unsubstitutedKtSignature.substitute(substitutor) },
|
||||
candidate.dispatchReceiverValue?.receiverExpression?.toKtReceiverValue(),
|
||||
candidate.chosenExtensionReceiverValue?.receiverExpression?.toKtReceiverValue(),
|
||||
candidate.dispatchReceiver?.toKtReceiverValue(),
|
||||
candidate.chosenExtensionReceiver?.toKtReceiverValue(),
|
||||
)
|
||||
}
|
||||
} else if (fir is FirImplicitInvokeCall) {
|
||||
|
||||
+1
-3
@@ -57,9 +57,7 @@ internal class KtFirVisibilityChecker(
|
||||
|
||||
val dispatchReceiverCanBeExplicit = candidateSymbol is KtCallableSymbol && !candidateSymbol.isExtension
|
||||
val explicitDispatchReceiver = runIf(dispatchReceiverCanBeExplicit) {
|
||||
receiverExpression
|
||||
?.getOrBuildFirSafe<FirExpression>(analysisSession.firResolveSession)
|
||||
?.let { ExpressionReceiverValue(it) }
|
||||
receiverExpression?.getOrBuildFirSafe<FirExpression>(analysisSession.firResolveSession)
|
||||
}
|
||||
|
||||
val candidateFirSymbol = candidateSymbol.firSymbol.fir as FirMemberDeclaration
|
||||
|
||||
+3
-3
@@ -53,12 +53,12 @@ class SingleCandidateResolver(
|
||||
callInfo,
|
||||
resolutionParameters.callableSymbol,
|
||||
explicitReceiverKind = explicitReceiverKind,
|
||||
dispatchReceiverValue = dispatchReceiverValue,
|
||||
dispatchReceiver = dispatchReceiverValue?.receiverExpression,
|
||||
givenExtensionReceiverOptions = listOfNotNull(
|
||||
if (explicitReceiverKind.isExtensionReceiver)
|
||||
callInfo.explicitReceiver?.let { ExpressionReceiverValue(it) }
|
||||
callInfo.explicitReceiver
|
||||
else
|
||||
implicitExtensionReceiverValue
|
||||
implicitExtensionReceiverValue?.receiverExpression
|
||||
),
|
||||
scope = null,
|
||||
)
|
||||
|
||||
+1
-2
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.originalForSubstitutionOverride
|
||||
import org.jetbrains.kotlin.fir.references.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ExpressionReceiverValue
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeDiagnosticWithCandidates
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError
|
||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||
@@ -51,7 +50,7 @@ object FirReassignmentAndInvisibleSetterChecker : FirVariableAssignmentChecker()
|
||||
context.session,
|
||||
context.findClosest()!!,
|
||||
context.containingDeclarations,
|
||||
ExpressionReceiverValue(expression.dispatchReceiver),
|
||||
expression.dispatchReceiver,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticPropertyAccessor
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.resolve.SupertypeSupplier
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.FirSimpleSyntheticPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ReceiverValue
|
||||
@@ -30,7 +31,7 @@ object FirJavaVisibilityChecker : FirVisibilityChecker() {
|
||||
symbol: FirBasedSymbol<*>,
|
||||
useSiteFile: FirFile,
|
||||
containingDeclarations: List<FirDeclaration>,
|
||||
dispatchReceiver: ReceiverValue?,
|
||||
dispatchReceiver: FirExpression?,
|
||||
session: FirSession,
|
||||
isCallToPropertySetter: Boolean,
|
||||
supertypeSupplier: SupertypeSupplier
|
||||
|
||||
@@ -12,13 +12,12 @@ import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticPropertyAccessor
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.toReference
|
||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
||||
import org.jetbrains.kotlin.fir.references.FirThisReference
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ExpressionReceiverValue
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitReceiverValue
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ReceiverValue
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.getContainingFile
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||
@@ -54,7 +53,7 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
||||
symbol: FirBasedSymbol<*>,
|
||||
useSiteFile: FirFile,
|
||||
containingDeclarations: List<FirDeclaration>,
|
||||
dispatchReceiver: ReceiverValue?,
|
||||
dispatchReceiver: FirExpression?,
|
||||
session: FirSession,
|
||||
isCallToPropertySetter: Boolean,
|
||||
supertypeSupplier: SupertypeSupplier
|
||||
@@ -95,7 +94,7 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
||||
session: FirSession,
|
||||
useSiteFile: FirFile,
|
||||
containingDeclarations: List<FirDeclaration>,
|
||||
dispatchReceiver: ReceiverValue?,
|
||||
dispatchReceiver: FirExpression?,
|
||||
isCallToPropertySetter: Boolean = false,
|
||||
staticQualifierClassForCallable: FirRegularClass? = null,
|
||||
// There's no need to check if containing class is visible in case we check if a member might be overridden in a subclass
|
||||
@@ -172,16 +171,16 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
||||
|
||||
private fun FirMemberDeclaration.containingNonLocalClass(
|
||||
session: FirSession,
|
||||
dispatchReceiverValue: ReceiverValue?,
|
||||
dispatchReceiver: FirExpression?,
|
||||
containingUseSiteDeclarations: List<FirDeclaration>,
|
||||
supertypeSupplier: SupertypeSupplier
|
||||
): FirClassLikeDeclaration? {
|
||||
return when (this) {
|
||||
is FirCallableDeclaration -> {
|
||||
if (dispatchReceiverValue != null) {
|
||||
if (dispatchReceiver != null) {
|
||||
val baseReceiverType = dispatchReceiverClassTypeOrNull()
|
||||
if (baseReceiverType != null) {
|
||||
dispatchReceiverValue.type.findClassRepresentation(baseReceiverType, session)?.toSymbol(session)?.fir?.let {
|
||||
dispatchReceiver.typeRef.coneType.findClassRepresentation(baseReceiverType, session)?.toSymbol(session)?.fir?.let {
|
||||
return it
|
||||
}
|
||||
}
|
||||
@@ -220,7 +219,7 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
||||
session: FirSession,
|
||||
useSiteFile: FirFile,
|
||||
containingDeclarations: List<FirDeclaration>,
|
||||
dispatchReceiver: ReceiverValue?,
|
||||
dispatchReceiver: FirExpression?,
|
||||
isCallToPropertySetter: Boolean = false,
|
||||
supertypeSupplier: SupertypeSupplier
|
||||
): Boolean {
|
||||
@@ -288,7 +287,7 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
||||
symbol: FirBasedSymbol<*>,
|
||||
useSiteFile: FirFile,
|
||||
containingDeclarations: List<FirDeclaration>,
|
||||
dispatchReceiver: ReceiverValue?,
|
||||
dispatchReceiver: FirExpression?,
|
||||
session: FirSession,
|
||||
isCallToPropertySetter: Boolean,
|
||||
supertypeSupplier: SupertypeSupplier
|
||||
@@ -304,7 +303,7 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
||||
symbol: FirBasedSymbol<*>,
|
||||
containingDeclarationOfUseSite: List<FirDeclaration>,
|
||||
ownerLookupTag: ConeClassLikeLookupTag,
|
||||
dispatchReceiver: ReceiverValue?,
|
||||
dispatchReceiver: FirExpression?,
|
||||
isVariableOrNamedFunction: Boolean,
|
||||
session: FirSession
|
||||
): Boolean {
|
||||
@@ -332,7 +331,7 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
||||
|
||||
val dispatchReceiverParameterClassLookupTag = dispatchReceiverParameterClassSymbol.toLookupTag()
|
||||
val dispatchReceiverValueOwnerLookupTag =
|
||||
dispatchReceiver.type.findClassRepresentation(
|
||||
dispatchReceiver.typeRef.coneType.findClassRepresentation(
|
||||
dispatchReceiverParameterClassLookupTag.constructClassType(
|
||||
Array(dispatchReceiverParameterClassSymbol.fir.typeParameters.size) { ConeStarProjection },
|
||||
isNullable = true
|
||||
@@ -342,21 +341,13 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
||||
|
||||
if (dispatchReceiverParameterClassLookupTag != dispatchReceiverValueOwnerLookupTag) return false
|
||||
if (fir.visibility == Visibilities.PrivateToThis) {
|
||||
when (dispatchReceiver) {
|
||||
is ExpressionReceiverValue -> {
|
||||
val explicitReceiver = dispatchReceiver.explicitReceiver
|
||||
if (explicitReceiver !is FirThisReceiverExpression) {
|
||||
return false
|
||||
}
|
||||
if (explicitReceiver.calleeReference.boundSymbol != dispatchReceiverParameterClassSymbol) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
is ImplicitReceiverValue<*> -> {
|
||||
if (dispatchReceiver.boundSymbol != dispatchReceiverParameterClassSymbol) {
|
||||
when (val dispatchReceiverReference = dispatchReceiver.toReference()) {
|
||||
is FirThisReference -> {
|
||||
if (dispatchReceiverReference.boundSymbol != dispatchReceiverParameterClassSymbol) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
else -> return false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -385,7 +376,7 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
||||
|
||||
private fun canSeeProtectedMemberOf(
|
||||
containingUseSiteClass: FirClass,
|
||||
dispatchReceiver: ReceiverValue?,
|
||||
dispatchReceiver: FirExpression?,
|
||||
ownerLookupTag: ConeClassLikeLookupTag,
|
||||
session: FirSession,
|
||||
isVariableOrNamedFunction: Boolean,
|
||||
@@ -410,20 +401,17 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
||||
}
|
||||
|
||||
private fun doesReceiverFitForProtectedVisibility(
|
||||
dispatchReceiver: ReceiverValue?,
|
||||
dispatchReceiver: FirExpression?,
|
||||
containingUseSiteClass: FirClass,
|
||||
ownerLookupTag: ConeClassLikeLookupTag,
|
||||
isSyntheticProperty: Boolean,
|
||||
session: FirSession
|
||||
): Boolean {
|
||||
if (dispatchReceiver == null) return true
|
||||
var dispatchReceiverType = dispatchReceiver.type
|
||||
if (dispatchReceiver is ExpressionReceiverValue) {
|
||||
val explicitReceiver = dispatchReceiver.explicitReceiver
|
||||
if (explicitReceiver is FirPropertyAccessExpression && explicitReceiver.calleeReference is FirSuperReference) {
|
||||
// Special 'super' case: type of this, not of super, should be taken for the check below
|
||||
dispatchReceiverType = explicitReceiver.dispatchReceiver.typeRef.coneType
|
||||
}
|
||||
var dispatchReceiverType = dispatchReceiver.typeRef.coneType
|
||||
if (dispatchReceiver is FirPropertyAccessExpression && dispatchReceiver.calleeReference is FirSuperReference) {
|
||||
// Special 'super' case: type of this, not of super, should be taken for the check below
|
||||
dispatchReceiverType = dispatchReceiver.dispatchReceiver.typeRef.coneType
|
||||
}
|
||||
val typeCheckerState = session.typeContext.newTypeCheckerState(
|
||||
errorTypesEqualToAnything = false,
|
||||
@@ -448,8 +436,9 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
||||
return false
|
||||
}
|
||||
|
||||
private fun ReceiverValue?.ownerIfCompanion(session: FirSession): ConeClassLikeLookupTag? =
|
||||
(this?.type as? ConeClassLikeType)?.lookupTag?.ownerIfCompanion(session)
|
||||
private fun FirExpression?.ownerIfCompanion(session: FirSession): ConeClassLikeLookupTag? =
|
||||
// TODO: what if there is an intersection type from smartcast?
|
||||
(this?.typeRef?.coneType as? ConeClassLikeType)?.lookupTag?.ownerIfCompanion(session)
|
||||
|
||||
// monitorEnter/monitorExit are the only functions which are accessed "illegally" (see kotlin/util/Synchronized.kt).
|
||||
// Since they are intrinsified in the codegen, FIR should treat it as visible.
|
||||
@@ -464,7 +453,7 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
||||
protected fun canSeeProtectedMemberOf(
|
||||
usedSymbol: FirBasedSymbol<*>,
|
||||
containingDeclarationOfUseSite: List<FirDeclaration>,
|
||||
dispatchReceiver: ReceiverValue?,
|
||||
dispatchReceiver: FirExpression?,
|
||||
ownerLookupTag: ConeClassLikeLookupTag,
|
||||
session: FirSession,
|
||||
isVariableOrNamedFunction: Boolean,
|
||||
|
||||
@@ -36,9 +36,7 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.SmartcastStability
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.applyIf
|
||||
|
||||
interface Receiver
|
||||
|
||||
interface ReceiverValue : Receiver {
|
||||
interface ReceiverValue {
|
||||
val type: ConeKotlinType
|
||||
|
||||
val receiverExpression: FirExpression
|
||||
@@ -51,8 +49,7 @@ interface ReceiverValue : Receiver {
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: should inherit just Receiver, not ReceiverValue
|
||||
abstract class AbstractExplicitReceiver<E : FirExpression> : Receiver {
|
||||
abstract class AbstractExplicitReceiver<E : FirExpression> {
|
||||
abstract val explicitReceiver: FirExpression
|
||||
}
|
||||
|
||||
@@ -62,11 +59,11 @@ abstract class AbstractExplicitReceiverValue<E : FirExpression> : AbstractExplic
|
||||
get() = explicitReceiver.typeRef.coneTypeSafe()
|
||||
?: ConeErrorType(ConeIntermediateDiagnostic("No type calculated for: ${explicitReceiver.renderWithType()}")) // TODO: assert here
|
||||
|
||||
override val receiverExpression: FirExpression
|
||||
final override val receiverExpression: FirExpression
|
||||
get() = explicitReceiver
|
||||
}
|
||||
|
||||
open class ExpressionReceiverValue(
|
||||
class ExpressionReceiverValue(
|
||||
override val explicitReceiver: FirExpression
|
||||
) : AbstractExplicitReceiverValue<FirExpression>(), ReceiverValue {
|
||||
override fun scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirTypeScope? {
|
||||
@@ -121,10 +118,46 @@ sealed class ImplicitReceiverValue<S : FirBasedSymbol<*>>(
|
||||
|
||||
override fun scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirTypeScope? = implicitScope
|
||||
|
||||
private val originalReceiverExpression: FirExpression =
|
||||
private var receiverIsSmartcasted: Boolean = false
|
||||
private var originalReceiverExpression: FirExpression =
|
||||
receiverExpression(boundSymbol, type, contextReceiverNumber, inaccessibleReceiver)
|
||||
final override var receiverExpression: FirExpression = originalReceiverExpression
|
||||
private set
|
||||
private var _receiverExpression: FirExpression? = null
|
||||
|
||||
private fun computeReceiverExpression(): FirExpression {
|
||||
_receiverExpression?.let { return it }
|
||||
val actualReceiverExpression = if (receiverIsSmartcasted) {
|
||||
buildSmartCastExpression {
|
||||
originalExpression = originalReceiverExpression
|
||||
this.source = originalExpression.source?.fakeElement(KtFakeSourceElementKind.SmartCastExpression)
|
||||
smartcastType = buildResolvedTypeRef {
|
||||
source = originalReceiverExpression.typeRef.source?.fakeElement(KtFakeSourceElementKind.SmartCastedTypeRef)
|
||||
type = this@ImplicitReceiverValue.type
|
||||
}
|
||||
typesFromSmartCast = listOf(type)
|
||||
smartcastStability = SmartcastStability.STABLE_VALUE
|
||||
typeRef = smartcastType.copyWithNewSourceKind(KtFakeSourceElementKind.ImplicitTypeRef)
|
||||
}
|
||||
} else {
|
||||
originalReceiverExpression
|
||||
}
|
||||
_receiverExpression = actualReceiverExpression
|
||||
return actualReceiverExpression
|
||||
}
|
||||
|
||||
/**
|
||||
* The idea of receiver expression for implicit receivers is following:
|
||||
* - Implicit receivers are mutable because of smartcasts
|
||||
* - Expression of implicit receiver may be used during call resolution and then stored for later. This implies necesserity
|
||||
* to keep receiver expression independent of state of corresponding implicit value
|
||||
* - In the same time we don't want to create new receiver expression for each access in sake of performance
|
||||
* All those statements lead to the current implementation:
|
||||
* - original receiver expression (without smartcast) always stored inside receiver value and can not be changed (TODO: except builder inference)
|
||||
* - we keep information about was there smartcast or not in [receiverIsSmartcasted] field
|
||||
* - we cache computed receiver expression in [_receiverExpression] field
|
||||
* - if type of receiver value was changed this cache is dropped
|
||||
*/
|
||||
final override val receiverExpression: FirExpression
|
||||
get() = computeReceiverExpression()
|
||||
|
||||
@RequiresOptIn
|
||||
annotation class ImplicitReceiverInternals
|
||||
@@ -132,7 +165,8 @@ sealed class ImplicitReceiverValue<S : FirBasedSymbol<*>>(
|
||||
@Deprecated(level = DeprecationLevel.ERROR, message = "Builder inference should not modify implicit receivers. KT-54708")
|
||||
fun updateTypeInBuilderInference(type: ConeKotlinType) {
|
||||
this.type = type
|
||||
receiverExpression = receiverExpression(boundSymbol, type, contextReceiverNumber, inaccessibleReceiver)
|
||||
originalReceiverExpression = receiverExpression(boundSymbol, type, contextReceiverNumber, inaccessibleReceiver)
|
||||
_receiverExpression = null
|
||||
implicitScope = type.scope(
|
||||
useSiteSession = useSiteSession,
|
||||
scopeSession = scopeSession,
|
||||
@@ -147,24 +181,10 @@ sealed class ImplicitReceiverValue<S : FirBasedSymbol<*>>(
|
||||
@ImplicitReceiverInternals
|
||||
fun updateTypeFromSmartcast(type: ConeKotlinType) {
|
||||
if (type == this.type) return
|
||||
if (!mutable) throw IllegalStateException("Cannot mutate an immutable ImplicitReceiverValue")
|
||||
if (!mutable) error("Cannot mutate an immutable ImplicitReceiverValue")
|
||||
this.type = type
|
||||
receiverExpression = if (type == originalReceiverExpression.typeRef.coneType) {
|
||||
originalReceiverExpression
|
||||
} else {
|
||||
buildSmartCastExpression {
|
||||
originalExpression = originalReceiverExpression
|
||||
this.source = originalExpression.source?.fakeElement(KtFakeSourceElementKind.SmartCastExpression)
|
||||
smartcastType = buildResolvedTypeRef {
|
||||
source = originalReceiverExpression.typeRef.source?.fakeElement(KtFakeSourceElementKind.SmartCastedTypeRef)
|
||||
this.type = type
|
||||
}
|
||||
typesFromSmartCast = listOf(type)
|
||||
smartcastStability = SmartcastStability.STABLE_VALUE
|
||||
typeRef = smartcastType.copyWithNewSourceKind(KtFakeSourceElementKind.ImplicitTypeRef)
|
||||
}
|
||||
}
|
||||
|
||||
receiverIsSmartcasted = type != this.originalType
|
||||
_receiverExpression = null
|
||||
implicitScope = type.scope(
|
||||
useSiteSession = useSiteSession,
|
||||
scopeSession = scopeSession,
|
||||
|
||||
@@ -30,10 +30,10 @@ class Candidate(
|
||||
// - in case a use-site receiver is explicit
|
||||
// - in some cases with static entities, no matter is a use-site receiver explicit or not
|
||||
// OR we may have here a kind of ImplicitReceiverValue (non-statics only)
|
||||
override var dispatchReceiverValue: ReceiverValue?,
|
||||
override var dispatchReceiver: FirExpression?,
|
||||
// In most cases, it contains zero or single element
|
||||
// More than one, only in case of context receiver group
|
||||
val givenExtensionReceiverOptions: List<ReceiverValue>,
|
||||
val givenExtensionReceiverOptions: List<FirExpression>,
|
||||
override val explicitReceiverKind: ExplicitReceiverKind,
|
||||
private val constraintSystemFactory: InferenceComponents.ConstraintSystemFactory,
|
||||
private val baseSystem: ConstraintStorage,
|
||||
@@ -44,7 +44,7 @@ class Candidate(
|
||||
val isFromOriginalTypeInPresenceOfSmartCast: Boolean = false,
|
||||
) : AbstractCandidate() {
|
||||
|
||||
var systemInitialized: Boolean = false
|
||||
private var systemInitialized: Boolean = false
|
||||
val system: NewConstraintSystemImpl by lazy(LazyThreadSafetyMode.NONE) {
|
||||
val system = constraintSystemFactory.createConstraintSystem()
|
||||
system.addOtherSystem(baseSystem)
|
||||
@@ -80,7 +80,7 @@ class Candidate(
|
||||
var currentApplicability = CandidateApplicability.RESOLVED
|
||||
private set
|
||||
|
||||
override var chosenExtensionReceiverValue: ReceiverValue? = givenExtensionReceiverOptions.singleOrNull()
|
||||
override var chosenExtensionReceiver: FirExpression? = givenExtensionReceiverOptions.singleOrNull()
|
||||
|
||||
var contextReceiverArguments: List<FirExpression>? = null
|
||||
|
||||
@@ -103,11 +103,13 @@ class Candidate(
|
||||
|
||||
var passedStages: Int = 0
|
||||
|
||||
// FirExpressionStub can be located here in case of callable reference resolution
|
||||
fun dispatchReceiverExpression(): FirExpression =
|
||||
dispatchReceiverValue?.receiverExpression?.takeIf { it !is FirExpressionStub } ?: FirNoReceiverExpression
|
||||
dispatchReceiver?.takeIf { it !is FirExpressionStub } ?: FirNoReceiverExpression
|
||||
|
||||
// FirExpressionStub can be located here in case of callable reference resolution
|
||||
fun chosenExtensionReceiverExpression(): FirExpression =
|
||||
chosenExtensionReceiverValue?.receiverExpression?.takeIf { it !is FirExpressionStub } ?: FirNoReceiverExpression
|
||||
chosenExtensionReceiver?.takeIf { it !is FirExpressionStub } ?: FirNoReceiverExpression
|
||||
|
||||
fun contextReceiverArguments(): List<FirExpression> =
|
||||
contextReceiverArguments ?: emptyList()
|
||||
|
||||
+12
-7
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.fir.scopes.impl.originalForWrappedIntegerOperator
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.classId
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzerContext
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
@@ -54,8 +55,8 @@ class CandidateFactory private constructor(
|
||||
symbol: FirBasedSymbol<*>,
|
||||
explicitReceiverKind: ExplicitReceiverKind,
|
||||
scope: FirScope?,
|
||||
dispatchReceiverValue: ReceiverValue? = null,
|
||||
givenExtensionReceiverOptions: List<ReceiverValue> = emptyList(),
|
||||
dispatchReceiver: FirExpression? = null,
|
||||
givenExtensionReceiverOptions: List<FirExpression> = emptyList(),
|
||||
objectsByName: Boolean = false,
|
||||
isFromOriginalTypeInPresenceOfSmartCast: Boolean = false,
|
||||
): Candidate {
|
||||
@@ -64,7 +65,7 @@ class CandidateFactory private constructor(
|
||||
|
||||
val result = Candidate(
|
||||
symbol,
|
||||
dispatchReceiverValue,
|
||||
dispatchReceiver,
|
||||
givenExtensionReceiverOptions,
|
||||
explicitReceiverKind,
|
||||
context.inferenceComponents.constraintSystemFactory,
|
||||
@@ -74,7 +75,7 @@ class CandidateFactory private constructor(
|
||||
isFromCompanionObjectTypeScope = when (explicitReceiverKind) {
|
||||
ExplicitReceiverKind.EXTENSION_RECEIVER ->
|
||||
givenExtensionReceiverOptions.singleOrNull().isCandidateFromCompanionObjectTypeScope()
|
||||
ExplicitReceiverKind.DISPATCH_RECEIVER -> dispatchReceiverValue.isCandidateFromCompanionObjectTypeScope()
|
||||
ExplicitReceiverKind.DISPATCH_RECEIVER -> dispatchReceiver.isCandidateFromCompanionObjectTypeScope()
|
||||
// The following cases are not applicable for companion objects.
|
||||
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, ExplicitReceiverKind.BOTH_RECEIVERS -> false
|
||||
},
|
||||
@@ -117,8 +118,12 @@ class CandidateFactory private constructor(
|
||||
|
||||
private fun ReceiverValue?.isCandidateFromCompanionObjectTypeScope(): Boolean {
|
||||
val expressionReceiverValue = this as? ExpressionReceiverValue ?: return false
|
||||
val resolvedQualifier = (expressionReceiverValue.explicitReceiver as? FirResolvedQualifier) ?: return false
|
||||
val originClassOfCandidate = expressionReceiverValue.type.classId ?: return false
|
||||
return expressionReceiverValue.explicitReceiver.isCandidateFromCompanionObjectTypeScope()
|
||||
}
|
||||
|
||||
private fun FirExpression?.isCandidateFromCompanionObjectTypeScope(): Boolean {
|
||||
val resolvedQualifier = this as? FirResolvedQualifier ?: return false
|
||||
val originClassOfCandidate = this.typeRef.coneType.classId ?: return false
|
||||
return (resolvedQualifier.symbol?.fir as? FirRegularClass)?.companionObjectSymbol?.classId == originClassOfCandidate
|
||||
}
|
||||
|
||||
@@ -134,7 +139,7 @@ class CandidateFactory private constructor(
|
||||
}
|
||||
return Candidate(
|
||||
symbol,
|
||||
dispatchReceiverValue = null,
|
||||
dispatchReceiver = null,
|
||||
givenExtensionReceiverOptions = emptyList(),
|
||||
explicitReceiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
|
||||
context.inferenceComponents.constraintSystemFactory,
|
||||
|
||||
+41
-27
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||
import org.jetbrains.kotlin.fir.matchingParameterFunctionType
|
||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
||||
import org.jetbrains.kotlin.fir.references.FirThisReference
|
||||
import org.jetbrains.kotlin.fir.resolve.directExpansionType
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.ConeTypeParameterBasedTypeVariable
|
||||
@@ -25,10 +26,8 @@ import org.jetbrains.kotlin.fir.resolve.inference.csBuilder
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.hasBuilderInferenceAnnotation
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeExplicitTypeParameterConstraintPosition
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
|
||||
import org.jetbrains.kotlin.fir.scopes.FirUnstableSmartcastTypeScope
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions
|
||||
import org.jetbrains.kotlin.fir.scopes.*
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.SyntheticSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||
@@ -135,17 +134,17 @@ object CheckExtensionReceiver : ResolutionStage() {
|
||||
}
|
||||
|
||||
private fun Candidate.prepareReceivers(
|
||||
argumentExtensionReceiverValue: ReceiverValue,
|
||||
argumentExtensionReceiver: FirExpression,
|
||||
expectedType: ConeKotlinType,
|
||||
context: ResolutionContext,
|
||||
): ReceiverDescription {
|
||||
val argumentType = captureFromTypeParameterUpperBoundIfNeeded(
|
||||
argumentType = argumentExtensionReceiverValue.type,
|
||||
argumentType = argumentExtensionReceiver.typeRef.coneType,
|
||||
expectedType = expectedType,
|
||||
session = context.session
|
||||
).let { prepareCapturedType(it, context) }
|
||||
|
||||
return ReceiverDescription(argumentExtensionReceiverValue.receiverExpression, argumentType)
|
||||
return ReceiverDescription(argumentExtensionReceiver, argumentType)
|
||||
}
|
||||
|
||||
private class ReceiverDescription(
|
||||
@@ -163,7 +162,7 @@ object CheckDispatchReceiver : ResolutionStage() {
|
||||
}
|
||||
}
|
||||
|
||||
val dispatchReceiverValueType = candidate.dispatchReceiverValue?.type ?: return
|
||||
val dispatchReceiverValueType = candidate.dispatchReceiver?.typeRef?.coneType ?: return
|
||||
val isReceiverNullable = !AbstractNullabilityChecker.isSubtypeOfAny(context.session.typeContext, dispatchReceiverValueType)
|
||||
|
||||
val isCandidateFromUnstableSmartcast =
|
||||
@@ -205,9 +204,10 @@ object CheckContextReceivers : ResolutionStage() {
|
||||
candidate.substitutor.substituteOrSelf(it.typeRef.coneType)
|
||||
}?.takeUnless { it.isEmpty() } ?: return
|
||||
|
||||
val receiverGroups: List<List<ImplicitReceiverValue<*>>> =
|
||||
val receiverGroups: List<List<FirExpression>> =
|
||||
context.bodyResolveContext.towerDataContext.towerDataElements.asReversed().mapNotNull { towerDataElement ->
|
||||
towerDataElement.implicitReceiver?.let(::listOf) ?: towerDataElement.contextReceiverGroup
|
||||
towerDataElement.implicitReceiver?.receiverExpression?.let(::listOf)
|
||||
?: towerDataElement.contextReceiverGroup?.map { it.receiverExpression }
|
||||
}
|
||||
|
||||
val resultingContextReceiverArguments = mutableListOf<FirExpression>()
|
||||
@@ -236,7 +236,7 @@ object CheckContextReceivers : ResolutionStage() {
|
||||
|
||||
private fun Candidate.findClosestMatchingReceivers(
|
||||
expectedType: ConeKotlinType,
|
||||
receiverGroups: List<List<ImplicitReceiverValue<*>>>,
|
||||
receiverGroups: List<List<FirExpression>>,
|
||||
context: ResolutionContext,
|
||||
): List<ReceiverDescription> {
|
||||
for (receiverGroup in receiverGroups) {
|
||||
@@ -259,18 +259,24 @@ object CheckDslScopeViolation : ResolutionStage() {
|
||||
private val dslMarkerClassId = ClassId.fromString("kotlin/DslMarker")
|
||||
|
||||
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
|
||||
fun checkReceiverValue(receiverValue: ReceiverValue?) {
|
||||
if (receiverValue is ImplicitReceiverValue<*>) {
|
||||
receiverValue.checkImpl(
|
||||
fun checkReceiver(receiver: FirExpression?) {
|
||||
val thisReference = receiver?.toReference() as? FirThisReference ?: return
|
||||
if (thisReference.isImplicit) {
|
||||
checkImpl(
|
||||
candidate,
|
||||
sink,
|
||||
context,
|
||||
{ receiverValue.getDslMarkersOfImplicitReceiver(context) }
|
||||
) { a, b -> a == b }
|
||||
{ getDslMarkersOfImplicitReceiver(thisReference.boundSymbol, receiver.typeRef.coneType, context) }
|
||||
) {
|
||||
// TODO: is there better alternative?
|
||||
// Here we rely on the fact that receiver expression of implicit receiver value can not be changed
|
||||
// during resolution of one single call
|
||||
it.receiverExpression == receiver
|
||||
}
|
||||
}
|
||||
}
|
||||
checkReceiverValue(candidate.dispatchReceiverValue)
|
||||
checkReceiverValue(candidate.chosenExtensionReceiverValue)
|
||||
checkReceiver(candidate.dispatchReceiver)
|
||||
checkReceiver(candidate.chosenExtensionReceiver)
|
||||
|
||||
// For value of builtin functional type with implicit extension receiver, the receiver is passed as the first argument rather than
|
||||
// an extension receiver of the `invoke` call. Hence, we need to specially handle this case.
|
||||
@@ -299,31 +305,31 @@ object CheckDslScopeViolation : ResolutionStage() {
|
||||
// ```
|
||||
// `useX()` is a call to `invoke` with `useX` as the dispatch receiver. In the FIR tree, extension receiver is represented as an
|
||||
// implicit `this` expression passed as the first argument.
|
||||
if (candidate.dispatchReceiverValue?.type?.fullyExpandedType(context.session)?.isSomeFunctionType(context.session) == true &&
|
||||
if (candidate.dispatchReceiver?.typeRef?.coneType?.fullyExpandedType(context.session)?.isSomeFunctionType(context.session) == true &&
|
||||
(candidate.symbol as? FirNamedFunctionSymbol)?.name == OperatorNameConventions.INVOKE
|
||||
) {
|
||||
val firstArg = candidate.argumentMapping?.keys?.firstOrNull() as? FirThisReceiverExpression ?: return
|
||||
if (!firstArg.isImplicit) return
|
||||
firstArg.checkImpl(
|
||||
checkImpl(
|
||||
candidate,
|
||||
sink,
|
||||
context,
|
||||
{ firstArg.getDslMarkersOfThisReceiverExpression(context) }
|
||||
) { receiver, thisExpression -> receiver.boundSymbol == thisExpression.calleeReference.boundSymbol }
|
||||
) { it.boundSymbol == firstArg.calleeReference.boundSymbol }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the implicit receiver (represented as an object of type `T`) violates DSL scope rules.
|
||||
*/
|
||||
private fun <T> T.checkImpl(
|
||||
private fun checkImpl(
|
||||
candidate: Candidate,
|
||||
sink: CheckerSink,
|
||||
context: ResolutionContext,
|
||||
dslMarkersProvider: () -> Set<ClassId>,
|
||||
isImplicitReceiverMatching: (ImplicitReceiverValue<*>, T) -> Boolean,
|
||||
isImplicitReceiverMatching: (ImplicitReceiverValue<*>) -> Boolean,
|
||||
) {
|
||||
val resolvedReceiverIndex = context.bodyResolveContext.implicitReceiverStack.indexOfFirst { isImplicitReceiverMatching(it, this) }
|
||||
val resolvedReceiverIndex = context.bodyResolveContext.implicitReceiverStack.indexOfFirst { isImplicitReceiverMatching(it) }
|
||||
if (resolvedReceiverIndex == -1) return
|
||||
val closerReceivers = context.bodyResolveContext.implicitReceiverStack.drop(resolvedReceiverIndex + 1)
|
||||
if (closerReceivers.isEmpty()) return
|
||||
@@ -335,6 +341,14 @@ object CheckDslScopeViolation : ResolutionStage() {
|
||||
}
|
||||
|
||||
private fun ImplicitReceiverValue<*>.getDslMarkersOfImplicitReceiver(context: ResolutionContext): Set<ClassId> {
|
||||
return CheckDslScopeViolation.getDslMarkersOfImplicitReceiver(boundSymbol, type, context)
|
||||
}
|
||||
|
||||
private fun getDslMarkersOfImplicitReceiver(
|
||||
boundSymbol: FirBasedSymbol<*>?,
|
||||
type: ConeKotlinType,
|
||||
context: ResolutionContext,
|
||||
): Set<ClassId> {
|
||||
return buildSet {
|
||||
(boundSymbol as? FirAnonymousFunctionSymbol)?.fir?.matchingParameterFunctionType?.let {
|
||||
// collect annotations in the function type at declaration site. For example, the `@A` and `@B` in the following code.
|
||||
@@ -550,7 +564,7 @@ internal object CheckVisibility : CheckerStage() {
|
||||
val visible = visibilityChecker.isVisible(
|
||||
declaration,
|
||||
candidate.callInfo,
|
||||
dispatchReceiverValue = null
|
||||
dispatchReceiver = null
|
||||
)
|
||||
if (!visible) {
|
||||
sink.yieldDiagnostic(VisibilityError)
|
||||
@@ -696,8 +710,8 @@ private val DYNAMIC_EXTENSION_ANNOTATION_CLASS_ID: ClassId = ClassId.topLevel(DY
|
||||
internal object ProcessDynamicExtensionAnnotation : ResolutionStage() {
|
||||
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
|
||||
if (candidate.symbol.origin === FirDeclarationOrigin.DynamicScope) return
|
||||
val extensionReceiver = candidate.chosenExtensionReceiverValue ?: return
|
||||
val argumentIsDynamic = extensionReceiver.type is ConeDynamicType
|
||||
val extensionReceiver = candidate.chosenExtensionReceiver ?: return
|
||||
val argumentIsDynamic = extensionReceiver.typeRef.coneType is ConeDynamicType
|
||||
val parameterIsDynamic = (candidate.symbol as? FirCallableSymbol)?.resolvedReceiverTypeRef?.type is ConeDynamicType
|
||||
if (parameterIsDynamic != argumentIsDynamic ||
|
||||
parameterIsDynamic && !candidate.symbol.hasAnnotation(DYNAMIC_EXTENSION_ANNOTATION_CLASS_ID, context.session)
|
||||
|
||||
+30
-19
@@ -13,10 +13,9 @@ import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.getExplicitBackingField
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
||||
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
||||
import org.jetbrains.kotlin.fir.expressions.FirSmartCastExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildSmartCastExpression
|
||||
import org.jetbrains.kotlin.fir.references.FirThisReference
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousObjectSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
|
||||
@@ -30,14 +29,18 @@ import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||
fun FirVisibilityChecker.isVisible(
|
||||
declaration: FirMemberDeclaration,
|
||||
callInfo: CallInfo,
|
||||
dispatchReceiverValue: ReceiverValue?
|
||||
dispatchReceiver: FirExpression?
|
||||
): Boolean {
|
||||
val staticQualifierForCallable = runIf(declaration is FirCallableDeclaration && declaration.isStatic) {
|
||||
val explicitReceiver = (dispatchReceiverValue as? ExpressionReceiverValue)?.explicitReceiver
|
||||
when (val classLikeSymbol = (explicitReceiver as? FirResolvedQualifier)?.symbol) {
|
||||
val staticQualifierForCallable = runIf(
|
||||
declaration is FirCallableDeclaration &&
|
||||
declaration.isStatic &&
|
||||
isExplicitReceiverExpression(dispatchReceiver)
|
||||
) {
|
||||
when (val classLikeSymbol = (dispatchReceiver as? FirResolvedQualifier)?.symbol) {
|
||||
is FirRegularClassSymbol -> classLikeSymbol.fir
|
||||
is FirTypeAliasSymbol -> classLikeSymbol.fullyExpandedClass(callInfo.session)?.fir
|
||||
is FirAnonymousObjectSymbol, null -> null
|
||||
is FirAnonymousObjectSymbol,
|
||||
null -> null
|
||||
}
|
||||
}
|
||||
return isVisible(
|
||||
@@ -45,7 +48,7 @@ fun FirVisibilityChecker.isVisible(
|
||||
callInfo.session,
|
||||
callInfo.containingFile,
|
||||
callInfo.containingDeclarations,
|
||||
dispatchReceiverValue,
|
||||
dispatchReceiver,
|
||||
staticQualifierClassForCallable = staticQualifierForCallable,
|
||||
isCallToPropertySetter = callInfo.callSite is FirVariableAssignment
|
||||
)
|
||||
@@ -57,28 +60,29 @@ fun FirVisibilityChecker.isVisible(
|
||||
): Boolean {
|
||||
val callInfo = candidate.callInfo
|
||||
|
||||
if (!isVisible(declaration, callInfo, candidate.dispatchReceiverValue)) {
|
||||
if (!isVisible(declaration, callInfo, candidate.dispatchReceiver)) {
|
||||
val dispatchReceiverWithoutSmartCastType =
|
||||
removeSmartCastTypeForAttemptToFitVisibility(candidate.dispatchReceiverValue, candidate.callInfo.session) ?: return false
|
||||
removeSmartCastTypeForAttemptToFitVisibility(candidate.dispatchReceiver, candidate.callInfo.session) ?: return false
|
||||
|
||||
if (!isVisible(declaration, callInfo, dispatchReceiverWithoutSmartCastType)) return false
|
||||
|
||||
candidate.dispatchReceiverValue = dispatchReceiverWithoutSmartCastType
|
||||
candidate.dispatchReceiver = dispatchReceiverWithoutSmartCastType
|
||||
}
|
||||
|
||||
val backingField = declaration.getBackingFieldIfApplicable()
|
||||
if (backingField != null) {
|
||||
candidate.hasVisibleBackingField = isVisible(backingField, callInfo, candidate.dispatchReceiverValue)
|
||||
candidate.hasVisibleBackingField = isVisible(backingField, callInfo, candidate.dispatchReceiver)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun removeSmartCastTypeForAttemptToFitVisibility(dispatchReceiverValue: ReceiverValue?, session: FirSession): ReceiverValue? {
|
||||
private fun removeSmartCastTypeForAttemptToFitVisibility(dispatchReceiver: FirExpression?, session: FirSession): FirExpression? {
|
||||
val expressionWithSmartcastIfStable =
|
||||
(dispatchReceiverValue?.receiverExpression as? FirSmartCastExpression)?.takeIf { it.isStable } ?: return null
|
||||
(dispatchReceiver as? FirSmartCastExpression)?.takeIf { it.isStable } ?: return null
|
||||
|
||||
if (dispatchReceiverValue.type.isNullableNothing) return null
|
||||
val receiverType = dispatchReceiver.typeRef.coneType
|
||||
if (receiverType.isNullableNothing) return null
|
||||
|
||||
val originalExpression = expressionWithSmartcastIfStable.originalExpression
|
||||
val originalType = originalExpression.typeRef.coneType
|
||||
@@ -87,11 +91,11 @@ private fun removeSmartCastTypeForAttemptToFitVisibility(dispatchReceiverValue:
|
||||
|
||||
// Basically, this `if` is just for sake of optimizaton
|
||||
// We have only nullability enhancement, here, so return initial smart cast receiver value
|
||||
if (originalTypeNotNullable == dispatchReceiverValue.type) return null
|
||||
if (originalTypeNotNullable == receiverType) return null
|
||||
|
||||
val expressionForReceiver = with(session.typeContext) {
|
||||
when {
|
||||
originalType.isNullableType() && !dispatchReceiverValue.type.isNullableType() ->
|
||||
originalType.isNullableType() && !receiverType.isNullableType() ->
|
||||
buildSmartCastExpression {
|
||||
source = originalExpression.source?.fakeElement(KtFakeSourceElementKind.SmartCastExpression)
|
||||
this.originalExpression = originalExpression
|
||||
@@ -107,7 +111,7 @@ private fun removeSmartCastTypeForAttemptToFitVisibility(dispatchReceiverValue:
|
||||
}
|
||||
}
|
||||
|
||||
return ExpressionReceiverValue(expressionForReceiver)
|
||||
return expressionForReceiver
|
||||
|
||||
}
|
||||
|
||||
@@ -123,3 +127,10 @@ private fun FirMemberDeclaration.getBackingFieldIfApplicable(): FirBackingField?
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun isExplicitReceiverExpression(receiverExpression: FirExpression?): Boolean {
|
||||
if (receiverExpression == null) return false
|
||||
// Only FirThisReference may be a reference in implicit receiver
|
||||
val thisReference = receiverExpression.toReference() as? FirThisReference ?: return true
|
||||
return !thisReference.isImplicit
|
||||
}
|
||||
|
||||
+20
-7
@@ -90,11 +90,13 @@ internal abstract class FirBaseTowerResolveTask(
|
||||
includeInnerConstructors: Boolean = extensionReceiver != null,
|
||||
contextReceiverGroup: ContextReceiverGroup? = null,
|
||||
dispatchReceiverForStatics: ExpressionReceiverValue? = null
|
||||
): ScopeTowerLevel = ScopeTowerLevel(
|
||||
components, this,
|
||||
givenExtensionReceiverOptions = contextReceiverGroup ?: listOfNotNull(extensionReceiver),
|
||||
withHideMembersOnly, includeInnerConstructors, dispatchReceiverForStatics
|
||||
)
|
||||
): ScopeTowerLevel {
|
||||
return ScopeTowerLevel(
|
||||
components, this,
|
||||
givenExtensionReceiverOptions = createExtensionReceiverOptions(contextReceiverGroup, extensionReceiver),
|
||||
withHideMembersOnly, includeInnerConstructors, dispatchReceiverForStatics
|
||||
)
|
||||
}
|
||||
|
||||
protected fun FirScope.toScopeTowerLevelForStaticWithImplicitDispatchReceiver(
|
||||
staticOwnerOwnerSymbol: FirRegularClassSymbol? = null,
|
||||
@@ -123,7 +125,7 @@ internal abstract class FirBaseTowerResolveTask(
|
||||
skipSynthetics: Boolean = false,
|
||||
) = MemberScopeTowerLevel(
|
||||
components, this,
|
||||
givenExtensionReceiverOptions = contextReceiverGroup ?: listOfNotNull(extensionReceiver),
|
||||
givenExtensionReceiverOptions = createExtensionReceiverOptions(contextReceiverGroup, extensionReceiver),
|
||||
skipSynthetics = skipSynthetics,
|
||||
)
|
||||
|
||||
@@ -132,9 +134,20 @@ internal abstract class FirBaseTowerResolveTask(
|
||||
otherContextReceiverGroup: ContextReceiverGroup? = null,
|
||||
) = ContextReceiverGroupMemberScopeTowerLevel(
|
||||
components, this,
|
||||
givenExtensionReceiverOptions = otherContextReceiverGroup ?: listOfNotNull(extensionReceiver),
|
||||
givenExtensionReceiverOptions = createExtensionReceiverOptions(otherContextReceiverGroup, extensionReceiver),
|
||||
)
|
||||
|
||||
private fun createExtensionReceiverOptions(
|
||||
contextReceiverGroup: ContextReceiverGroup?,
|
||||
extensionReceiverValue: ReceiverValue?,
|
||||
): List<FirExpression> {
|
||||
return when {
|
||||
contextReceiverGroup != null -> contextReceiverGroup.map { it.receiverExpression }
|
||||
extensionReceiverValue != null -> listOf(extensionReceiverValue.receiverExpression)
|
||||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
protected inline fun enumerateTowerLevels(
|
||||
parentGroup: TowerGroup = TowerGroup.EmptyRoot,
|
||||
onScope: (FirScope, FirRegularClassSymbol?, TowerGroup) -> Unit,
|
||||
|
||||
+1
-1
@@ -117,7 +117,7 @@ class FirTowerResolver(
|
||||
it,
|
||||
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
|
||||
scope,
|
||||
dispatchReceiver,
|
||||
dispatchReceiver?.receiverExpression,
|
||||
givenExtensionReceiverOptions = emptyList()
|
||||
),
|
||||
context
|
||||
|
||||
+5
-4
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.calls.tower
|
||||
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.*
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
@@ -78,11 +79,11 @@ private class TowerScopeLevelProcessor(
|
||||
) : TowerScopeLevel.TowerScopeLevelProcessor<FirBasedSymbol<*>> {
|
||||
override fun consumeCandidate(
|
||||
symbol: FirBasedSymbol<*>,
|
||||
dispatchReceiverValue: ReceiverValue?,
|
||||
givenExtensionReceiverOptions: List<ReceiverValue>,
|
||||
dispatchReceiver: FirExpression?,
|
||||
givenExtensionReceiverOptions: List<FirExpression>,
|
||||
scope: FirScope,
|
||||
objectsByName: Boolean,
|
||||
isFromOriginalTypeInPresenceOfSmartCast: Boolean
|
||||
isFromOriginalTypeInPresenceOfSmartCast: Boolean,
|
||||
) {
|
||||
resultCollector.consumeCandidate(
|
||||
group, candidateFactory.createCandidate(
|
||||
@@ -90,7 +91,7 @@ private class TowerScopeLevelProcessor(
|
||||
symbol,
|
||||
explicitReceiverKind,
|
||||
scope,
|
||||
dispatchReceiverValue,
|
||||
dispatchReceiver,
|
||||
givenExtensionReceiverOptions,
|
||||
objectsByName,
|
||||
isFromOriginalTypeInPresenceOfSmartCast
|
||||
|
||||
+13
-12
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isInner
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirSmartCastExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildResolvedQualifier
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
@@ -55,8 +56,8 @@ abstract class TowerScopeLevel {
|
||||
interface TowerScopeLevelProcessor<in T : FirBasedSymbol<*>> {
|
||||
fun consumeCandidate(
|
||||
symbol: T,
|
||||
dispatchReceiverValue: ReceiverValue?,
|
||||
givenExtensionReceiverOptions: List<ReceiverValue>,
|
||||
dispatchReceiver: FirExpression?,
|
||||
givenExtensionReceiverOptions: List<FirExpression>,
|
||||
scope: FirScope,
|
||||
objectsByName: Boolean = false,
|
||||
isFromOriginalTypeInPresenceOfSmartCast: Boolean = false,
|
||||
@@ -74,7 +75,7 @@ abstract class TowerScopeLevel {
|
||||
class MemberScopeTowerLevel(
|
||||
private val bodyResolveComponents: BodyResolveComponents,
|
||||
val dispatchReceiverValue: ReceiverValue,
|
||||
private val givenExtensionReceiverOptions: List<ReceiverValue>,
|
||||
private val givenExtensionReceiverOptions: List<FirExpression>,
|
||||
private val skipSynthetics: Boolean,
|
||||
) : TowerScopeLevel() {
|
||||
private val scopeSession: ScopeSession get() = bodyResolveComponents.scopeSession
|
||||
@@ -156,7 +157,7 @@ class MemberScopeTowerLevel(
|
||||
empty = false
|
||||
output.consumeCandidate(
|
||||
symbol,
|
||||
dispatchReceiverValue,
|
||||
dispatchReceiverValue.receiverExpression,
|
||||
givenExtensionReceiverOptions = emptyList(),
|
||||
scope
|
||||
)
|
||||
@@ -198,8 +199,8 @@ class MemberScopeTowerLevel(
|
||||
|
||||
val dispatchReceiverToUse = when {
|
||||
isFromOriginalTypeInPresenceOfSmartCast ->
|
||||
getOriginalReceiverExpressionIfStableSmartCast()?.let(::ExpressionReceiverValue)
|
||||
else -> dispatchReceiverValue
|
||||
getOriginalReceiverExpressionIfStableSmartCast()
|
||||
else -> dispatchReceiverValue.receiverExpression
|
||||
}
|
||||
|
||||
output.consumeCandidate(
|
||||
@@ -283,7 +284,7 @@ class MemberScopeTowerLevel(
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirCallableSymbol<*>.hasConsistentExtensionReceiver(givenExtensionReceivers: List<ReceiverValue>): Boolean {
|
||||
private fun FirCallableSymbol<*>.hasConsistentExtensionReceiver(givenExtensionReceivers: List<FirExpression>): Boolean {
|
||||
return givenExtensionReceivers.isNotEmpty() == hasExtensionReceiver()
|
||||
}
|
||||
}
|
||||
@@ -291,7 +292,7 @@ class MemberScopeTowerLevel(
|
||||
class ContextReceiverGroupMemberScopeTowerLevel(
|
||||
bodyResolveComponents: BodyResolveComponents,
|
||||
contextReceiverGroup: ContextReceiverGroup,
|
||||
givenExtensionReceiverOptions: List<ReceiverValue> = emptyList(),
|
||||
givenExtensionReceiverOptions: List<FirExpression> = emptyList(),
|
||||
) : TowerScopeLevel() {
|
||||
private val memberScopeLevels = contextReceiverGroup.map {
|
||||
MemberScopeTowerLevel(bodyResolveComponents, it, givenExtensionReceiverOptions, false)
|
||||
@@ -320,7 +321,7 @@ class ContextReceiverGroupMemberScopeTowerLevel(
|
||||
class ScopeTowerLevel(
|
||||
private val bodyResolveComponents: BodyResolveComponents,
|
||||
val scope: FirScope,
|
||||
private val givenExtensionReceiverOptions: List<ReceiverValue>,
|
||||
private val givenExtensionReceiverOptions: List<FirExpression>,
|
||||
private val withHideMembersOnly: Boolean,
|
||||
private val includeInnerConstructors: Boolean,
|
||||
private val dispatchReceiverForStatics: ExpressionReceiverValue?
|
||||
@@ -383,7 +384,7 @@ class ScopeTowerLevel(
|
||||
)
|
||||
|
||||
return givenExtensionReceiverOptions.none { extensionReceiver ->
|
||||
val extensionReceiverType = extensionReceiver.type
|
||||
val extensionReceiverType = extensionReceiver.resultType.coneType
|
||||
// If some receiver is non class like, we should not skip it
|
||||
if (extensionReceiverType !is ConeClassLikeType) return@none true
|
||||
|
||||
@@ -417,7 +418,7 @@ class ScopeTowerLevel(
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
processor.consumeCandidate(
|
||||
unwrappedCandidate as T,
|
||||
dispatchReceiverValue,
|
||||
dispatchReceiverValue?.receiverExpression,
|
||||
givenExtensionReceiverOptions,
|
||||
scope
|
||||
)
|
||||
@@ -463,7 +464,7 @@ class ScopeTowerLevel(
|
||||
scope.processClassifiersByName(info.name) {
|
||||
empty = false
|
||||
processor.consumeCandidate(
|
||||
it, dispatchReceiverValue = null,
|
||||
it, dispatchReceiver = null,
|
||||
givenExtensionReceiverOptions = emptyList(),
|
||||
scope = scope,
|
||||
objectsByName = true
|
||||
|
||||
+25
-11
@@ -10,14 +10,16 @@ import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.hasAnnotation
|
||||
import org.jetbrains.kotlin.fir.expressions.FirResolvable
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.Candidate
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitExtensionReceiverValue
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ResolutionContext
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.candidate
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ChainedSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.replaceStubsAndTypeVariablesToErrors
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirCallCompletionResultsWriterTransformer
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.visitors.FirDefaultTransformer
|
||||
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
||||
@@ -72,12 +74,12 @@ class FirBuilderInferenceSession(
|
||||
}
|
||||
|
||||
private fun Candidate.isSuitableForBuilderInference(): Boolean {
|
||||
val extensionReceiver = chosenExtensionReceiverValue
|
||||
val dispatchReceiver = dispatchReceiverValue
|
||||
val extensionReceiver = chosenExtensionReceiver
|
||||
val dispatchReceiver = dispatchReceiver
|
||||
return when {
|
||||
extensionReceiver == null && dispatchReceiver == null -> false
|
||||
dispatchReceiver?.type?.containsStubType() == true -> true
|
||||
extensionReceiver?.type?.containsStubType() == true -> symbol.fir.hasBuilderInferenceAnnotation(session)
|
||||
dispatchReceiver?.typeRef?.coneType?.containsStubType() == true -> true
|
||||
extensionReceiver?.typeRef?.coneType?.containsStubType() == true -> symbol.fir.hasBuilderInferenceAnnotation(session)
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
@@ -251,7 +253,6 @@ class FirBuilderInferenceSession(
|
||||
}
|
||||
|
||||
// TODO: support diagnostics, see [CoroutineInferenceSession#updateCalls]
|
||||
|
||||
val completionResultsWriter = components.callCompleter.createCompletionResultsWriter(substitutor)
|
||||
for ((call, _) in partiallyResolvedCalls) {
|
||||
call.transformSingle(completionResultsWriter, null)
|
||||
@@ -260,19 +261,32 @@ class FirBuilderInferenceSession(
|
||||
}
|
||||
}
|
||||
|
||||
class FirStubTypeTransformer(
|
||||
private val substitutor: ConeSubstitutor
|
||||
) : FirDefaultTransformer<Nothing?>() {
|
||||
class FirStubTypeTransformer(private val substitutor: ConeSubstitutor) : FirDefaultTransformer<Nothing?>() {
|
||||
|
||||
override fun <E : FirElement> transformElement(element: E, data: Nothing?): E {
|
||||
// All resolvable nodes should be implemented separately to cover substitution of receivers in the candidate
|
||||
if (element is FirResolvable) {
|
||||
element.candidate()?.let { processCandidate(it) }
|
||||
}
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return (element.transformChildren(this, data) as E)
|
||||
return element.transformChildren(this, data = null) as E
|
||||
}
|
||||
|
||||
override fun transformResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: Nothing?): FirTypeRef =
|
||||
substitutor.substituteOrNull(resolvedTypeRef.type)?.let {
|
||||
resolvedTypeRef.withReplacedConeType(it)
|
||||
} ?: resolvedTypeRef
|
||||
|
||||
/*
|
||||
* We should manually update all receivers in the all not completed candidates, because not all calls with candidates
|
||||
* contained in partiallyResolvedCalls and candidate stores not receiver values, which are updated, (TODO: remove this comment after removal of updating values)
|
||||
* and receivers of candidates are not direct FIR children of calls, so they won't be visited during regular transformChildren
|
||||
*/
|
||||
private fun processCandidate(candidate: Candidate) {
|
||||
candidate.dispatchReceiver = candidate.dispatchReceiver?.transform(this, data = null)
|
||||
candidate.chosenExtensionReceiver = candidate.chosenExtensionReceiver?.transform(this, data = null)
|
||||
candidate.contextReceiverArguments = candidate.contextReceiverArguments?.map { it.transform(this, data = null) }
|
||||
}
|
||||
}
|
||||
|
||||
private val BUILDER_INFERENCE_ANNOTATION_CLASS_ID: ClassId = ClassId.topLevel(BUILDER_INFERENCE_ANNOTATION_FQ_NAME)
|
||||
|
||||
+2
-3
@@ -72,8 +72,8 @@ class FirDelegatedPropertyInferenceSession(
|
||||
if (callee.candidate.system.hasContradiction) return true
|
||||
|
||||
val hasStubType =
|
||||
callee.candidate.chosenExtensionReceiverValue?.type?.containsStubType() ?: false
|
||||
|| callee.candidate.dispatchReceiverValue?.type?.containsStubType() ?: false
|
||||
callee.candidate.chosenExtensionReceiver?.typeRef?.coneType?.containsStubType() ?: false
|
||||
|| callee.candidate.dispatchReceiver?.typeRef?.coneType?.containsStubType() ?: false
|
||||
|
||||
if (!hasStubType) {
|
||||
return true
|
||||
@@ -165,7 +165,6 @@ class FirDelegatedPropertyInferenceSession(
|
||||
fun completeCandidates(): List<FirResolvable> {
|
||||
val commonSystem = components.session.inferenceComponents.createConstraintSystem()
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val notCompletedCalls = partiallyResolvedCalls.mapNotNull { partiallyResolvedCall ->
|
||||
partiallyResolvedCall.first.takeIf { resolvable ->
|
||||
resolvable.candidate() != null
|
||||
|
||||
+3
-3
@@ -13,10 +13,10 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirOuterClassTypeParameterRef
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
||||
import org.jetbrains.kotlin.fir.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.AbstractCallInfo
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.AbstractCandidate
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ReceiverValue
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ResolutionDiagnostic
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
@@ -538,10 +538,10 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
|
||||
override val applicability: CandidateApplicability
|
||||
) : AbstractCandidate() {
|
||||
|
||||
override val dispatchReceiverValue: ReceiverValue?
|
||||
override val dispatchReceiver: FirExpression?
|
||||
get() = null
|
||||
|
||||
override val chosenExtensionReceiverValue: ReceiverValue?
|
||||
override val chosenExtensionReceiver: FirExpression?
|
||||
get() = null
|
||||
|
||||
override val explicitReceiverKind: ExplicitReceiverKind
|
||||
|
||||
+1
@@ -9,6 +9,7 @@ import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.labelName
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.*
|
||||
|
||||
+3
-2
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.calls
|
||||
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintSystemError
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
@@ -12,8 +13,8 @@ import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
|
||||
|
||||
abstract class AbstractCandidate {
|
||||
abstract val symbol: FirBasedSymbol<*>
|
||||
abstract val dispatchReceiverValue: ReceiverValue?
|
||||
abstract val chosenExtensionReceiverValue: ReceiverValue?
|
||||
abstract val dispatchReceiver: FirExpression?
|
||||
abstract val chosenExtensionReceiver: FirExpression?
|
||||
abstract val explicitReceiverKind: ExplicitReceiverKind
|
||||
abstract val callInfo: AbstractCallInfo
|
||||
abstract val diagnostics: List<ResolutionDiagnostic>
|
||||
|
||||
@@ -20,6 +20,7 @@ abstract class FirThisReference : FirReference() {
|
||||
abstract val labelName: String?
|
||||
abstract val boundSymbol: FirBasedSymbol<*>?
|
||||
abstract val contextReceiverNumber: Int
|
||||
abstract val isImplicit: Boolean
|
||||
|
||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitThisReference(this, data)
|
||||
|
||||
|
||||
+1
@@ -23,6 +23,7 @@ internal class FirExplicitThisReference(
|
||||
override var contextReceiverNumber: Int,
|
||||
) : FirThisReference() {
|
||||
override var boundSymbol: FirBasedSymbol<*>? = null
|
||||
override val isImplicit: Boolean = false
|
||||
|
||||
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {}
|
||||
|
||||
|
||||
+1
@@ -23,6 +23,7 @@ internal class FirImplicitThisReference(
|
||||
) : FirThisReference() {
|
||||
override val source: KtSourceElement? get() = null
|
||||
override val labelName: String? get() = null
|
||||
override val isImplicit: Boolean = true
|
||||
|
||||
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {}
|
||||
|
||||
|
||||
+2
@@ -484,6 +484,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
value = "null"
|
||||
isMutable = true
|
||||
}
|
||||
defaultFalse("isImplicit")
|
||||
}
|
||||
|
||||
impl(thisReference, "FirImplicitThisReference") {
|
||||
@@ -495,6 +496,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
default("boundSymbol") {
|
||||
isMutable = false
|
||||
}
|
||||
defaultTrue("isImplicit")
|
||||
}
|
||||
|
||||
impl(superReference, "FirExplicitSuperReference")
|
||||
|
||||
+1
@@ -687,6 +687,7 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
|
||||
+stringField("labelName", nullable = true)
|
||||
+field("boundSymbol", firBasedSymbolType, "*", nullable = true, withReplace = true)
|
||||
+intField("contextReceiverNumber", withReplace = true)
|
||||
+booleanField("isImplicit")
|
||||
}
|
||||
|
||||
typeRef.configure {
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_BACKEND_K2: JVM_IR
|
||||
// ISSUE: KT-58823
|
||||
// FILE: Base.java
|
||||
|
||||
|
||||
Reference in New Issue
Block a user