[FIR] Add ir support

This commit is contained in:
Nikolay Lunyak
2021-08-16 20:53:29 +03:00
committed by TeamCityServer
parent 8b918e12b2
commit 79ceaf03bf
11 changed files with 137 additions and 92 deletions
@@ -699,6 +699,7 @@ class Fir2IrDeclarationStorage(
private val FirProperty.fieldVisibility: Visibility private val FirProperty.fieldVisibility: Visibility
get() = when { get() = when {
hasExplicitBackingField -> backingField?.visibility ?: status.visibility
isLateInit -> setter?.visibility ?: status.visibility isLateInit -> setter?.visibility ?: status.visibility
isConst -> status.visibility isConst -> status.visibility
hasJvmFieldAnnotation -> status.visibility hasJvmFieldAnnotation -> status.visibility
@@ -798,7 +799,6 @@ class Fir2IrDeclarationStorage(
parent = irParent parent = irParent
} }
val type = property.returnTypeRef.toIrType() val type = property.returnTypeRef.toIrType()
val initializer = property.initializer
val delegate = property.delegate val delegate = property.delegate
val getter = property.getter val getter = property.getter
val setter = property.setter val setter = property.setter
@@ -810,14 +810,21 @@ class Fir2IrDeclarationStorage(
Name.identifier("${property.name}\$delegate"), true, delegate Name.identifier("${property.name}\$delegate"), true, delegate
) )
} else { } else {
val initializer = property.backingField?.initializer ?: property.initializer
// There are cases when we get here for properties
// that have no backing field. For example, in the
// funExpression.kt test there's an attempt
// to access the `javaClass` property of the `foo0`'s
// `block` argument
val typeToUse = property.backingField?.returnTypeRef?.toIrType() ?: type
createBackingField( createBackingField(
property, IrDeclarationOrigin.PROPERTY_BACKING_FIELD, property, IrDeclarationOrigin.PROPERTY_BACKING_FIELD,
components.visibilityConverter.convertToDescriptorVisibility(property.fieldVisibility), components.visibilityConverter.convertToDescriptorVisibility(property.fieldVisibility),
property.name, property.isVal, initializer, type property.name, property.isVal, initializer, typeToUse
).also { field -> ).also { field ->
if (initializer is FirConstExpression<*>) { if (initializer is FirConstExpression<*>) {
// TODO: Normally we shouldn't have error type here // TODO: Normally we shouldn't have error type here
val constType = initializer.typeRef.toIrType().takeIf { it !is IrErrorType } ?: type val constType = initializer.typeRef.toIrType().takeIf { it !is IrErrorType } ?: typeToUse
field.initializer = factory.createExpressionBody(initializer.toIrConst(constType)) field.initializer = factory.createExpressionBody(initializer.toIrConst(constType))
} }
} }
@@ -158,7 +158,7 @@ internal class ClassMemberGenerator(
} }
fun convertPropertyContent(irProperty: IrProperty, property: FirProperty, containingClass: FirClass?): IrProperty { fun convertPropertyContent(irProperty: IrProperty, property: FirProperty, containingClass: FirClass?): IrProperty {
val initializer = property.initializer val initializer = property.backingField?.initializer ?: property.initializer
val delegate = property.delegate val delegate = property.delegate
val propertyType = property.returnTypeRef.toIrType() val propertyType = property.returnTypeRef.toIrType()
irProperty.initializeBackingField(property, initializerExpression = initializer ?: delegate) irProperty.initializeBackingField(property, initializerExpression = initializer ?: delegate)
@@ -29,6 +29,8 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import org.jetbrains.kotlin.fir.backend.* import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.declarations.utils.* import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
class Fir2IrLazyProperty( class Fir2IrLazyProperty(
@@ -88,6 +90,16 @@ class Fir2IrLazyProperty(
with(typeConverter) { fir.returnTypeRef.toIrType() } with(typeConverter) { fir.returnTypeRef.toIrType() }
} }
private fun toIrInitializer(initializer: FirExpression?): IrExpressionBody? {
return if (initializer is FirConstExpression<*>) {
// TODO: Normally we shouldn't have error type here
val constType = with(typeConverter) { initializer.typeRef.toIrType().takeIf { it !is IrErrorType } ?: type }
factory.createExpressionBody(initializer.toIrConst(constType))
} else {
null
}
}
@OptIn(ObsoleteDescriptorBasedAPI::class) @OptIn(ObsoleteDescriptorBasedAPI::class)
override var backingField: IrField? by lazyVar(lock) { override var backingField: IrField? by lazyVar(lock) {
// TODO: this checks are very preliminary, FIR resolve should determine backing field presence itself // TODO: this checks are very preliminary, FIR resolve should determine backing field presence itself
@@ -96,6 +108,26 @@ class Fir2IrLazyProperty(
!fir.isConst && (fir.modality == Modality.ABSTRACT || parent is IrClass && parent.isInterface) -> { !fir.isConst && (fir.modality == Modality.ABSTRACT || parent is IrClass && parent.isInterface) -> {
null null
} }
fir.hasExplicitBackingField -> {
with(declarationStorage) {
val backingFieldType = with(typeConverter) {
fir.backingField?.returnTypeRef?.toIrType()
}
val initializer = fir.backingField?.initializer ?: fir.initializer
val visibility = fir.backingField?.visibility ?: fir.visibility
createBackingField(
fir,
IrDeclarationOrigin.PROPERTY_BACKING_FIELD,
components.visibilityConverter.convertToDescriptorVisibility(visibility),
fir.name,
fir.isVal,
initializer,
backingFieldType
).also { field ->
field.initializer = toIrInitializer(initializer)
}
}
}
fir.initializer != null || fir.getter is FirDefaultPropertyGetter || fir.isVar && fir.setter is FirDefaultPropertySetter -> { fir.initializer != null || fir.getter is FirDefaultPropertyGetter || fir.isVar && fir.setter is FirDefaultPropertySetter -> {
with(declarationStorage) { with(declarationStorage) {
createBackingField( createBackingField(
@@ -103,12 +135,7 @@ class Fir2IrLazyProperty(
components.visibilityConverter.convertToDescriptorVisibility(fir.visibility), fir.name, fir.isVal, fir.initializer, components.visibilityConverter.convertToDescriptorVisibility(fir.visibility), fir.name, fir.isVal, fir.initializer,
type type
).also { field -> ).also { field ->
val initializer = fir.initializer field.initializer = toIrInitializer(fir.initializer)
if (initializer is FirConstExpression<*>) {
// TODO: Normally we shouldn't have error type here
val constType = with(typeConverter) { initializer.typeRef.toIrType().takeIf { it !is IrErrorType } ?: type }
field.initializer = factory.createExpressionBody(initializer.toIrConst(constType))
}
} }
} }
} }
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.hasExplicitBackingField
import org.jetbrains.kotlin.fir.declarations.utils.isInner import org.jetbrains.kotlin.fir.declarations.utils.isInner
import org.jetbrains.kotlin.fir.declarations.utils.isReferredViaField import org.jetbrains.kotlin.fir.declarations.utils.isReferredViaField
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
@@ -44,6 +45,7 @@ import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class FirCallResolver( class FirCallResolver(
private val components: FirAbstractBodyResolveTransformer.BodyResolveTransformerComponents, private val components: FirAbstractBodyResolveTransformer.BodyResolveTransformerComponents,
@@ -727,6 +729,11 @@ class FirCallResolver(
resolvedSymbol = coneSymbol resolvedSymbol = coneSymbol
} }
} }
if (coneSymbol.safeAs<FirPropertySymbol>()?.hasExplicitBackingField == true) {
return FirPropertyWithExplicitBackingFieldResolvedNamedReference(
source, name, candidate.symbol, candidate.hasVisibleBackingField
)
}
/* /*
* This `if` is an optimization for local variables and properties without type parameters * This `if` is an optimization for local variables and properties without type parameters
* Since they have no type variables, so we can don't run completion on them at all and create * Since they have no type variables, so we can don't run completion on them at all and create
@@ -18,11 +18,13 @@ import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticFunctionSymbol
import org.jetbrains.kotlin.fir.resolve.calls.ReceiverValue import org.jetbrains.kotlin.fir.resolve.calls.ReceiverValue
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirBackingFieldSymbol
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.types.AbstractTypeChecker import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
abstract class FirModuleVisibilityChecker : FirSessionComponent { abstract class FirModuleVisibilityChecker : FirSessionComponent {
abstract fun <T> isInFriendModule(declaration: T): Boolean where T : FirMemberDeclaration, T : FirDeclaration abstract fun <T> isInFriendModule(declaration: T): Boolean where T : FirMemberDeclaration, T : FirDeclaration
@@ -51,6 +53,23 @@ abstract class FirVisibilityChecker : FirSessionComponent {
} }
} }
private fun FirMemberDeclaration.getBackingFieldIfApplicable(): FirBackingField? {
val field = this.safeAs<FirProperty>()?.getExplicitBackingField()
?: return null
// This check prevents resolving protected and
// public fields.
if (
field.visibility == Visibilities.PrivateToThis ||
field.visibility == Visibilities.Private ||
field.visibility == Visibilities.Internal
) {
return field
}
return null
}
fun isVisible( fun isVisible(
declaration: FirMemberDeclaration, declaration: FirMemberDeclaration,
candidate: Candidate candidate: Candidate
@@ -71,7 +90,20 @@ abstract class FirVisibilityChecker : FirSessionComponent {
return true return true
} }
return isVisible(declaration, session, useSiteFile, containingDeclarations, candidate.dispatchReceiverValue) val visible = isVisible(declaration, session, useSiteFile, containingDeclarations, candidate.dispatchReceiverValue)
val backingField = declaration.getBackingFieldIfApplicable()
if (visible && backingField != null) {
candidate.hasVisibleBackingField = isVisible(
backingField,
session,
useSiteFile,
containingDeclarations,
candidate.dispatchReceiverValue,
)
}
return visible
} }
fun isVisible( fun isVisible(
@@ -277,6 +309,7 @@ val FirSession.visibilityChecker: FirVisibilityChecker by FirSession.sessionComp
fun FirBasedSymbol<*>.getOwnerLookupTag(): ConeClassLikeLookupTag? { fun FirBasedSymbol<*>.getOwnerLookupTag(): ConeClassLikeLookupTag? {
return when (this) { return when (this) {
is FirBackingFieldSymbol -> fir.propertySymbol.getOwnerLookupTag()
is FirClassLikeSymbol<*> -> { is FirClassLikeSymbol<*> -> {
if (classId.isLocal) { if (classId.isLocal) {
(fir as? FirRegularClass)?.containingClassForLocal() (fir as? FirRegularClass)?.containingClassForLocal()
@@ -11,7 +11,9 @@ import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.canNarrowDownGetterType
import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType
import org.jetbrains.kotlin.fir.declarations.utils.isFinal
import org.jetbrains.kotlin.fir.declarations.utils.isInner import org.jetbrains.kotlin.fir.declarations.utils.isInner
import org.jetbrains.kotlin.fir.declarations.utils.isLocal import org.jetbrains.kotlin.fir.declarations.utils.isLocal
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
@@ -187,6 +189,30 @@ internal fun typeForQualifierByDeclaration(declaration: FirDeclaration, resultTy
return null return null
} }
private fun FirPropertyWithExplicitBackingFieldResolvedNamedReference.getNarrowedDownSymbol(): FirBasedSymbol<*> {
val propertyReceiver = resolvedSymbol.safeAs<FirPropertySymbol>()
?: return resolvedSymbol
// This can happen in case of 2 properties referencing
// each other recursively. See: Jet81.fir.kt
if (
propertyReceiver.fir.returnTypeRef is FirImplicitTypeRef ||
propertyReceiver.fir.backingField?.returnTypeRef is FirImplicitTypeRef
) {
return resolvedSymbol
}
if (
propertyReceiver.isFinal &&
hasVisibleBackingField &&
propertyReceiver.canNarrowDownGetterType
) {
return propertyReceiver.fir.backingField?.symbol ?: resolvedSymbol
}
return resolvedSymbol
}
fun <T : FirResolvable> BodyResolveComponents.typeFromCallee(access: T): FirResolvedTypeRef { fun <T : FirResolvable> BodyResolveComponents.typeFromCallee(access: T): FirResolvedTypeRef {
return when (val newCallee = access.calleeReference) { return when (val newCallee = access.calleeReference) {
is FirErrorNamedReference -> is FirErrorNamedReference ->
@@ -198,16 +224,8 @@ fun <T : FirResolvable> BodyResolveComponents.typeFromCallee(access: T): FirReso
typeFromSymbol(newCallee.candidateSymbol, false) typeFromSymbol(newCallee.candidateSymbol, false)
} }
is FirPropertyWithExplicitBackingFieldResolvedNamedReference -> { is FirPropertyWithExplicitBackingFieldResolvedNamedReference -> {
val backingField = newCallee.resolvedSymbol val symbol = newCallee.getNarrowedDownSymbol()
.safeAs<FirPropertySymbol>() typeFromSymbol(symbol, false)
?.fir
?.backingField
if (newCallee.hasVisibleBackingField && backingField != null) {
typeFromSymbol(backingField.symbol, false)
} else {
typeFromSymbol(newCallee.resolvedSymbol, false)
}
} }
is FirResolvedNamedReference -> { is FirResolvedNamedReference -> {
typeFromSymbol(newCallee.resolvedSymbol, false) typeFromSymbol(newCallee.resolvedSymbol, false)
@@ -145,6 +145,8 @@ class Candidate(
fun extensionReceiverExpression(): FirExpression = fun extensionReceiverExpression(): FirExpression =
extensionReceiverValue?.receiverExpression?.takeIf { it !is FirExpressionStub } ?: FirNoReceiverExpression extensionReceiverValue?.receiverExpression?.takeIf { it !is FirExpressionStub } ?: FirNoReceiverExpression
var hasVisibleBackingField = false
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (javaClass != other?.javaClass) return false if (javaClass != other?.javaClass) return false
@@ -8,8 +8,11 @@ package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.FirImplementationDetail import org.jetbrains.kotlin.fir.FirImplementationDetail
import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.FirVisitor
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@OptIn(FirImplementationDetail::class) @OptIn(FirImplementationDetail::class)
@@ -32,3 +35,18 @@ class FirErrorReferenceWithCandidate(
) : FirNamedReferenceWithCandidate(source, name, candidate) { ) : FirNamedReferenceWithCandidate(source, name, candidate) {
override val isError: Boolean get() = true override val isError: Boolean get() = true
} }
class FirPropertyWithExplicitBackingFieldResolvedNamedReference(
override val source: FirSourceElement?,
override val name: Name,
override val resolvedSymbol: FirBasedSymbol<*>,
val hasVisibleBackingField: Boolean,
) : FirResolvedNamedReference() {
override val candidateSymbol: FirBasedSymbol<*>? get() = null
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {}
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirPropertyWithExplicitBackingFieldResolvedNamedReference {
return this
}
}
@@ -69,11 +69,6 @@ open class ExpressionReceiverValue(
} }
} }
class NarrowedExpressionReceiverValue(
explicitReceiver: FirExpression,
override val type: ConeKotlinType,
) : ExpressionReceiverValue(explicitReceiver)
sealed class ImplicitReceiverValue<S : FirBasedSymbol<*>>( sealed class ImplicitReceiverValue<S : FirBasedSymbol<*>>(
val boundSymbol: S, val boundSymbol: S,
type: ConeKotlinType, type: ConeKotlinType,
@@ -5,34 +5,21 @@
package org.jetbrains.kotlin.fir.resolve.calls.tower package org.jetbrains.kotlin.fir.resolve.calls.tower
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.asReversedFrozen import org.jetbrains.kotlin.fir.asReversedFrozen
import org.jetbrains.kotlin.fir.containingClass
import org.jetbrains.kotlin.fir.declarations.utils.canNarrowDownGetterType
import org.jetbrains.kotlin.fir.declarations.utils.isFinal
import org.jetbrains.kotlin.fir.declarations.utils.visibility
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.expressions.builder.buildExpressionStub import org.jetbrains.kotlin.fir.expressions.builder.buildExpressionStub
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.DoubleColonLHS import org.jetbrains.kotlin.fir.resolve.DoubleColonLHS
import org.jetbrains.kotlin.fir.resolve.FirTowerDataContext import org.jetbrains.kotlin.fir.resolve.FirTowerDataContext
import org.jetbrains.kotlin.fir.resolve.calls.* import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.descriptorUtil.HIDES_MEMBERS_NAME_LIST import org.jetbrains.kotlin.resolve.descriptorUtil.HIDES_MEMBERS_NAME_LIST
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
internal class TowerDataElementsForName( internal class TowerDataElementsForName(
name: Name, name: Name,
@@ -236,64 +223,12 @@ internal open class FirTowerResolveTask(
) )
} }
private fun FirPropertySymbol.hasAccessibleBackingField(info: CallInfo): Boolean {
val receiverContainer = containingClass()?.toSymbol(info.session)
if (!this.isFinal) {
return false
}
return when (fir.backingField?.visibility) {
Visibilities.Private -> {
info.containingDeclarations.any {
it.symbol == receiverContainer
}
}
Visibilities.Internal -> {
receiverContainer?.moduleData == info.containingFile.moduleData
}
else -> {
false
}
}
}
private fun FirExpression.getNarrowedDownReturnType(info: CallInfo): ConeKotlinType? {
val propertyReceiver = this.safeAs<FirQualifiedAccessExpression>()
?.calleeReference
?.safeAs<FirResolvedNamedReference>()
?.resolvedSymbol
?.safeAs<FirPropertySymbol>()
?: return null
// This can happen in case of 2 properties referencing
// each other recursively. See: Jet81.fir.kt
if (
propertyReceiver.fir.returnTypeRef is FirImplicitTypeRef ||
propertyReceiver.fir.backingField?.returnTypeRef is FirImplicitTypeRef
) {
return null
}
if (propertyReceiver.hasAccessibleBackingField(info) && propertyReceiver.canNarrowDownGetterType) {
return propertyReceiver.fir.backingField?.returnTypeRef?.coneType
}
return null
}
suspend fun runResolverForExpressionReceiver( suspend fun runResolverForExpressionReceiver(
info: CallInfo, info: CallInfo,
receiver: FirExpression, receiver: FirExpression,
parentGroup: TowerGroup = TowerGroup.EmptyRoot parentGroup: TowerGroup = TowerGroup.EmptyRoot
) { ) {
val narrowedType = receiver.getNarrowedDownReturnType(info) val explicitReceiverValue = ExpressionReceiverValue(receiver)
val explicitReceiverValue = if (narrowedType != null) {
NarrowedExpressionReceiverValue(receiver, narrowedType)
} else {
ExpressionReceiverValue(receiver)
}
processExtensionsThatHideMembers(info, explicitReceiverValue, parentGroup) processExtensionsThatHideMembers(info, explicitReceiverValue, parentGroup)
@@ -29,6 +29,9 @@ class FirProviderImpl(val session: FirSession, val kotlinScopeProvider: FirKotli
symbol.originalIfFakeOverride()?.let { symbol.originalIfFakeOverride()?.let {
return getFirCallableContainerFile(it) return getFirCallableContainerFile(it)
} }
if (symbol is FirBackingFieldSymbol) {
return getFirCallableContainerFile(symbol.fir.propertySymbol)
}
if (symbol is FirAccessorSymbol) { if (symbol is FirAccessorSymbol) {
val fir = symbol.fir val fir = symbol.fir
if (fir is FirSyntheticProperty) { if (fir is FirSyntheticProperty) {