From e7c9d761631d2c53ef07b3ab1b8063aab2a9d16b Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Tue, 16 Nov 2021 10:43:10 +0300 Subject: [PATCH] [FIR] Use SupertypeSupplier in type resolver for calculating supertypes This is needed to avoid problems with checking visibility of types which are used in supertypes during supertypes resolution in IDE, when supertypes of some class can be already computed, but not saved in class itself, but still lay in supertypeComputationSession There were 4 failing tests before this changes (all in `DiagnosisCompilerTestFE10TestdataTestGenerated$Tests$Exposed`): - testInternal - testInternalAndProtected - testProtected - testProtectedSameWay --- .../fir/java/FirJavaVisibilityChecker.kt | 5 ++- .../kotlin/fir/FirVisibilityChecker.kt | 42 ++++++++++++++----- .../kotlin/fir/resolve/FirTypeResolver.kt | 3 +- .../providers/impl/FirTypeResolverImpl.kt | 12 ++++-- .../FirSpecificTypeResolverTransformer.kt | 6 ++- .../transformers/FirSupertypesResolution.kt | 2 +- 6 files changed, 52 insertions(+), 18 deletions(-) diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaVisibilityChecker.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaVisibilityChecker.kt index cfbb2c4f453..de4aa493f3e 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaVisibilityChecker.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaVisibilityChecker.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticPropertyAccessor import org.jetbrains.kotlin.fir.declarations.utils.visibility +import org.jetbrains.kotlin.fir.resolve.SupertypeSupplier import org.jetbrains.kotlin.fir.resolve.calls.FirSimpleSyntheticPropertySymbol import org.jetbrains.kotlin.fir.resolve.calls.ReceiverValue import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol @@ -30,6 +31,7 @@ object FirJavaVisibilityChecker : FirVisibilityChecker() { dispatchReceiver: ReceiverValue?, session: FirSession, isCallToPropertySetter: Boolean, + supertypeSupplier: SupertypeSupplier ): Boolean { return when (declarationVisibility) { JavaVisibilities.ProtectedAndPackage, JavaVisibilities.ProtectedStaticVisibility -> { @@ -40,7 +42,8 @@ object FirJavaVisibilityChecker : FirVisibilityChecker() { if (canSeeProtectedMemberOf( containingDeclarations, dispatchReceiver, ownerLookupTag, session, isVariableOrNamedFunction = symbol is FirVariableSymbol || symbol is FirNamedFunctionSymbol || symbol is FirPropertyAccessorSymbol, - isSyntheticProperty = symbol.fir is FirSyntheticPropertyAccessor + isSyntheticProperty = symbol.fir is FirSyntheticPropertyAccessor, + supertypeSupplier ) ) return true diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt index 8d85162328e..896dc209505 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt @@ -50,6 +50,7 @@ abstract class FirVisibilityChecker : FirSessionComponent { dispatchReceiver: ReceiverValue?, session: FirSession, isCallToPropertySetter: Boolean, + supertypeSupplier: SupertypeSupplier ): Boolean { return true } @@ -67,6 +68,7 @@ abstract class FirVisibilityChecker : FirSessionComponent { // Such flag is not necessary in FE1.0, since there are full structure of fake overrides and containing declaration for overridden // is always visible since it's a supertype of a derived class. skipCheckForContainingClassVisibility: Boolean = false, + supertypeSupplier: SupertypeSupplier = SupertypeSupplier.Default ): Boolean { if (!isSpecificDeclarationVisible( declaration, @@ -74,7 +76,8 @@ abstract class FirVisibilityChecker : FirSessionComponent { useSiteFile, containingDeclarations, dispatchReceiver, - isCallToPropertySetter + isCallToPropertySetter, + supertypeSupplier ) ) { return false @@ -90,7 +93,8 @@ abstract class FirVisibilityChecker : FirSessionComponent { useSiteFile, containingDeclarations, dispatchReceiver, - isCallToPropertySetter + isCallToPropertySetter, + supertypeSupplier ) } } @@ -132,6 +136,7 @@ abstract class FirVisibilityChecker : FirSessionComponent { containingDeclarations: List, dispatchReceiver: ReceiverValue?, isCallToPropertySetter: Boolean = false, + supertypeSupplier: SupertypeSupplier ): Boolean { val symbol = declaration.symbol val provider = session.firProvider @@ -176,7 +181,8 @@ abstract class FirVisibilityChecker : FirSessionComponent { ownerId != null && canSeeProtectedMemberOf( containingDeclarations, dispatchReceiver, ownerId, session, isVariableOrNamedFunction = symbol is FirVariableSymbol || symbol is FirNamedFunctionSymbol || symbol is FirPropertyAccessorSymbol, - symbol.fir is FirSyntheticPropertyAccessor + symbol.fir is FirSyntheticPropertyAccessor, + supertypeSupplier ) } @@ -188,6 +194,7 @@ abstract class FirVisibilityChecker : FirSessionComponent { dispatchReceiver, session, isCallToPropertySetter, + supertypeSupplier ) } } @@ -200,6 +207,7 @@ abstract class FirVisibilityChecker : FirSessionComponent { dispatchReceiver: ReceiverValue?, session: FirSession, isCallToPropertySetter: Boolean, + supertypeSupplier: SupertypeSupplier ): Boolean private fun canSeePrivateMemberOf( @@ -243,14 +251,15 @@ abstract class FirVisibilityChecker : FirSessionComponent { ownerLookupTag: ConeClassLikeLookupTag, session: FirSession, isVariableOrNamedFunction: Boolean, - isSyntheticProperty: Boolean + isSyntheticProperty: Boolean, + supertypeSupplier: SupertypeSupplier ): Boolean { dispatchReceiver?.ownerIfCompanion(session)?.let { companionOwnerLookupTag -> - if (containingUseSiteClass.isSubClass(companionOwnerLookupTag, session)) return true + if (containingUseSiteClass.isSubClass(companionOwnerLookupTag, session, supertypeSupplier)) return true } return when { - !containingUseSiteClass.isSubClass(ownerLookupTag, session) -> false + !containingUseSiteClass.isSubClass(ownerLookupTag, session, supertypeSupplier) -> false isVariableOrNamedFunction -> doesReceiverFitForProtectedVisibility( dispatchReceiver, containingUseSiteClass, @@ -299,10 +308,21 @@ abstract class FirVisibilityChecker : FirSessionComponent { return false } - private fun FirClass.isSubClass(ownerLookupTag: ConeClassLikeLookupTag, session: FirSession): Boolean { + private fun FirClass.isSubClass( + ownerLookupTag: ConeClassLikeLookupTag, + session: FirSession, + supertypeSupplier: SupertypeSupplier + ): Boolean { if (classId.isSame(ownerLookupTag.classId)) return true - return lookupSuperTypes(this, lookupInterfaces = true, deep = true, session, substituteTypes = false).any { superType -> + return lookupSuperTypes( + this, + lookupInterfaces = true, + deep = true, + session, + substituteTypes = false, + supertypeSupplier + ).any { superType -> // Note: We check just classId here, so type substitution isn't needed ^ (we aren't interested in type arguments) (superType as? ConeClassLikeType)?.fullyExpandedType(session)?.lookupTag?.classId?.isSame(ownerLookupTag.classId) == true } @@ -327,7 +347,8 @@ abstract class FirVisibilityChecker : FirSessionComponent { ownerLookupTag: ConeClassLikeLookupTag, session: FirSession, isVariableOrNamedFunction: Boolean, - isSyntheticProperty: Boolean + isSyntheticProperty: Boolean, + supertypeSupplier: SupertypeSupplier ): Boolean { if (canSeePrivateMemberOf(containingDeclarationOfUseSite, ownerLookupTag, session)) return true @@ -340,7 +361,8 @@ abstract class FirVisibilityChecker : FirSessionComponent { ownerLookupTag, session, isVariableOrNamedFunction, - isSyntheticProperty + isSyntheticProperty, + supertypeSupplier ) ) return true } else if (containingDeclaration is FirFile) { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirTypeResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirTypeResolver.kt index 73e78eb6f40..ff1f4bb71ce 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirTypeResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirTypeResolver.kt @@ -18,7 +18,8 @@ abstract class FirTypeResolver : FirSessionComponent { scopeClassDeclaration: ScopeClassDeclaration, areBareTypesAllowed: Boolean, isOperandOfIsOperator: Boolean, - useSiteFile: FirFile? + useSiteFile: FirFile?, + supertypeSupplier: SupertypeSupplier ): ConeKotlinType } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt index e88823d0994..1253845ac76 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt @@ -78,6 +78,7 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() { private fun FirBasedSymbol<*>?.isVisible( useSiteFile: FirFile?, containingDeclarations: List, + supertypeSupplier: SupertypeSupplier ): Boolean { val declaration = this?.fir return if (useSiteFile != null && declaration is FirMemberDeclaration) { @@ -86,8 +87,9 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() { session, useSiteFile, containingDeclarations, - null, - false, + dispatchReceiver = null, + isCallToPropertySetter = false, + supertypeSupplier = supertypeSupplier ) } else { true @@ -98,6 +100,7 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() { typeRef: FirTypeRef, scopeClassDeclaration: ScopeClassDeclaration, useSiteFile: FirFile?, + supertypeSupplier: SupertypeSupplier ): Pair?, ConeSubstitutor?> { return when (typeRef) { is FirResolvedTypeRef -> { @@ -125,7 +128,7 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() { val resolvedSymbol = resolveSymbol(symbol, qualifier, qualifierResolver) - if (resolvedSymbol.isVisible(useSiteFile, containingDeclarations)) { + if (resolvedSymbol.isVisible(useSiteFile, containingDeclarations, supertypeSupplier)) { acceptedSymbol = resolvedSymbol substitutor = substitutorFromScope } else { @@ -451,11 +454,12 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() { areBareTypesAllowed: Boolean, isOperandOfIsOperator: Boolean, useSiteFile: FirFile?, + supertypeSupplier: SupertypeSupplier ): ConeKotlinType { return when (typeRef) { is FirResolvedTypeRef -> typeRef.type is FirUserTypeRef -> { - val (symbol, substitutor) = resolveToSymbol(typeRef, scopeClassDeclaration, useSiteFile) + val (symbol, substitutor) = resolveToSymbol(typeRef, scopeClassDeclaration, useSiteFile, supertypeSupplier) resolveUserType( typeRef, symbol, diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSpecificTypeResolverTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSpecificTypeResolverTransformer.kt index 7d27eaeeaed..2818b1a842b 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSpecificTypeResolverTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSpecificTypeResolverTransformer.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeUnexpectedTypeArgumentsError +import org.jetbrains.kotlin.fir.resolve.SupertypeSupplier import org.jetbrains.kotlin.fir.resolve.typeResolver import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef @@ -21,7 +22,8 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs class FirSpecificTypeResolverTransformer( override val session: FirSession, - private val errorTypeAsResolved: Boolean = true + private val errorTypeAsResolved: Boolean = true, + private val supertypeSupplier: SupertypeSupplier = SupertypeSupplier.Default ) : FirAbstractTreeTransformer(phase = FirResolvePhase.SUPER_TYPES) { private val typeResolver = session.typeResolver @@ -83,6 +85,7 @@ class FirSpecificTypeResolverTransformer( areBareTypesAllowed, isOperandOfIsOperator, currentFile, + supertypeSupplier ) ) } @@ -101,6 +104,7 @@ class FirSpecificTypeResolverTransformer( areBareTypesAllowed, isOperandOfIsOperator, currentFile, + supertypeSupplier ).takeIfAcceptable() return if (resolvedType != null && resolvedType !is ConeClassErrorType) { buildResolvedTypeRef { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypesResolution.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypesResolution.kt index fcce7c0a645..50a1dbf0a76 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypesResolution.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypesResolution.kt @@ -344,7 +344,7 @@ open class FirSupertypeResolverVisitor( supertypeComputationSession.startComputingSupertypes(classLikeDeclaration) val scopes = prepareScopes(classLikeDeclaration) - val transformer = FirSpecificTypeResolverTransformer(session) + val transformer = FirSpecificTypeResolverTransformer(session, supertypeSupplier = supertypeComputationSession.supertypesSupplier) val resolvedTypesRefs = transformer.withFile(useSiteFile) { resolveSuperTypeRefs( transformer,