FIR: Rework checking dispatch receivers applicability

Using `ownerLookupTag` might be wrong in case of private constuctors
 of inner classes: their owner is an Inner class, but expected
 dispach receiver is Outer
This commit is contained in:
Denis.Zharkov
2022-05-30 19:05:47 +03:00
committed by teamcity
parent 67e6687e89
commit 461d91a10e
8 changed files with 72 additions and 21 deletions
@@ -33496,6 +33496,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/visibility"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("innerClassDelegatingConstructorCallToPrivate.kt")
public void testInnerClassDelegatingConstructorCallToPrivate() throws Exception {
runTest("compiler/testData/diagnostics/tests/visibility/innerClassDelegatingConstructorCallToPrivate.kt");
}
@Test
@TestMetadata("innerConstructorThroughSubclass.kt")
public void testInnerConstructorThroughSubclass() throws Exception {
@@ -33496,6 +33496,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/visibility"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("innerClassDelegatingConstructorCallToPrivate.kt")
public void testInnerClassDelegatingConstructorCallToPrivate() throws Exception {
runTest("compiler/testData/diagnostics/tests/visibility/innerClassDelegatingConstructorCallToPrivate.kt");
}
@Test
@TestMetadata("innerConstructorThroughSubclass.kt")
public void testInnerConstructorThroughSubclass() throws Exception {
@@ -33496,6 +33496,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/visibility"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("innerClassDelegatingConstructorCallToPrivate.kt")
public void testInnerClassDelegatingConstructorCallToPrivate() throws Exception {
runTest("compiler/testData/diagnostics/tests/visibility/innerClassDelegatingConstructorCallToPrivate.kt");
}
@Test
@TestMetadata("innerConstructorThroughSubclass.kt")
public void testInnerConstructorThroughSubclass() throws Exception {
@@ -17,9 +17,6 @@ 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
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertyAccessorSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
@NoMutableState
object FirJavaVisibilityChecker : FirVisibilityChecker() {
@@ -40,7 +37,7 @@ object FirJavaVisibilityChecker : FirVisibilityChecker() {
} else {
val ownerLookupTag = symbol.getOwnerLookupTag() ?: return false
if (canSeeProtectedMemberOf(
containingDeclarations, dispatchReceiver, ownerLookupTag, session,
symbol, containingDeclarations, dispatchReceiver, ownerLookupTag, session,
isVariableOrNamedFunction = symbol.isVariableOrNamedFunction(),
isSyntheticProperty = symbol.fir is FirSyntheticPropertyAccessor,
supertypeSupplier
@@ -175,6 +175,7 @@ abstract class FirVisibilityChecker : FirSessionComponent {
else -> {
// Member: visible inside parent class, including all its member classes
canSeePrivateMemberOf(
symbol,
containingDeclarations,
ownerLookupTag,
dispatchReceiver,
@@ -191,7 +192,7 @@ abstract class FirVisibilityChecker : FirSessionComponent {
Visibilities.Protected -> {
val ownerId = symbol.getOwnerLookupTag()
ownerId != null && canSeeProtectedMemberOf(
containingDeclarations, dispatchReceiver, ownerId, session,
symbol, containingDeclarations, dispatchReceiver, ownerId, session,
isVariableOrNamedFunction = symbol.isVariableOrNamedFunction(),
symbol.fir is FirSyntheticPropertyAccessor,
supertypeSupplier
@@ -223,6 +224,7 @@ abstract class FirVisibilityChecker : FirSessionComponent {
): Boolean
private fun canSeePrivateMemberOf(
symbol: FirBasedSymbol<*>,
containingDeclarationOfUseSite: List<FirDeclaration>,
ownerLookupTag: ConeClassLikeLookupTag,
dispatchReceiver: ReceiverValue?,
@@ -231,6 +233,7 @@ abstract class FirVisibilityChecker : FirSessionComponent {
): Boolean {
ownerLookupTag.ownerIfCompanion(session)?.let { companionOwnerLookupTag ->
return canSeePrivateMemberOf(
symbol,
containingDeclarationOfUseSite,
companionOwnerLookupTag,
dispatchReceiver,
@@ -239,16 +242,25 @@ abstract class FirVisibilityChecker : FirSessionComponent {
)
}
val ownerSymbol = ownerLookupTag.toSymbol(session) ?: return true
if (dispatchReceiver != null) {
val dispatchReceiverParameterClassSymbol =
(symbol.fir as? FirCallableDeclaration)
?.propertyIfAccessor?.propertyIfBackingField
?.dispatchReceiverClassOrNull()?.toSymbol(session)
?: return true
val dispatchReceiverValueOwnerLookupTag =
dispatchReceiver.ownerIfCompanion(session)
?: dispatchReceiver?.type?.findClassRepresentation(
ownerLookupTag.constructClassType(Array(ownerSymbol.fir.typeParameters.size) { ConeStarProjection }, isNullable = true),
val dispatchReceiverParameterClassLookupTag = dispatchReceiverParameterClassSymbol.toLookupTag()
val dispatchReceiverValueOwnerLookupTag =
dispatchReceiver.type.findClassRepresentation(
dispatchReceiverParameterClassLookupTag.constructClassType(
Array(dispatchReceiverParameterClassSymbol.fir.typeParameters.size) { ConeStarProjection },
isNullable = true
),
session,
)
if (dispatchReceiverValueOwnerLookupTag != null && ownerLookupTag != dispatchReceiverValueOwnerLookupTag) return false
if (dispatchReceiverParameterClassLookupTag != dispatchReceiverValueOwnerLookupTag) return false
}
for (declaration in containingDeclarationOfUseSite) {
if (declaration !is FirClass) continue
@@ -373,6 +385,7 @@ abstract class FirVisibilityChecker : FirSessionComponent {
}
protected fun canSeeProtectedMemberOf(
usedSymbol: FirBasedSymbol<*>,
containingDeclarationOfUseSite: List<FirDeclaration>,
dispatchReceiver: ReceiverValue?,
ownerLookupTag: ConeClassLikeLookupTag,
@@ -382,6 +395,7 @@ abstract class FirVisibilityChecker : FirSessionComponent {
supertypeSupplier: SupertypeSupplier
): Boolean {
if (canSeePrivateMemberOf(
usedSymbol,
containingDeclarationOfUseSite,
ownerLookupTag,
dispatchReceiver,
@@ -431,19 +445,21 @@ val FirSession.visibilityChecker: FirVisibilityChecker by FirSession.sessionComp
fun FirBasedSymbol<*>.getOwnerLookupTag(): ConeClassLikeLookupTag? {
return when (this) {
is FirBackingFieldSymbol -> fir.propertySymbol.getOwnerLookupTag()
is FirClassLikeSymbol<*> -> {
if (classId.isLocal) {
(fir as? FirRegularClass)?.containingClassForLocal()
} else {
val ownerId = classId.outerClassId
ownerId?.let { ConeClassLikeLookupTagImpl(it) }
}
}
is FirClassLikeSymbol<*> -> getContainingClassLookupTag()
is FirCallableSymbol<*> -> containingClass()
else -> error("Unsupported owner search for ${fir.javaClass}: ${fir.render()}")
}
}
fun FirClassLikeSymbol<*>.getContainingClassLookupTag(): ConeClassLikeLookupTag? {
return if (classId.isLocal) {
(fir as? FirRegularClass)?.containingClassForLocal()
} else {
val ownerId = classId.outerClassId
ownerId?.let { ConeClassLikeLookupTagImpl(it) }
}
}
fun FirBasedSymbol<*>.isVariableOrNamedFunction(): Boolean {
return this is FirVariableSymbol || this is FirNamedFunctionSymbol || this is FirPropertyAccessorSymbol
}
@@ -5,10 +5,8 @@
package org.jetbrains.kotlin.fir
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
import org.jetbrains.kotlin.fir.declarations.utils.modality
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
@@ -127,3 +125,9 @@ private object CorrespondingProperty : FirDeclarationDataKey()
* The corresponding [FirProperty] if the current value parameter is a `val` or `var` declared inside the primary constructor.
*/
var FirValueParameter.correspondingProperty: FirProperty? by FirDeclarationDataRegistry.data(CorrespondingProperty)
val FirCallableDeclaration.propertyIfAccessor: FirCallableDeclaration
get() = (this as? FirPropertyAccessor)?.propertySymbol?.fir ?: this
val FirCallableDeclaration.propertyIfBackingField: FirCallableDeclaration
get() = (this as? FirBackingField)?.propertySymbol?.fir ?: this
@@ -0,0 +1,10 @@
// FIR_IDENTICAL
// SKIP_TXT
val w: Int = 2
class Outer {
private inner class Inner private constructor(x: Int) {
constructor() : this(w)
}
}
@@ -33586,6 +33586,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/visibility"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("innerClassDelegatingConstructorCallToPrivate.kt")
public void testInnerClassDelegatingConstructorCallToPrivate() throws Exception {
runTest("compiler/testData/diagnostics/tests/visibility/innerClassDelegatingConstructorCallToPrivate.kt");
}
@Test
@TestMetadata("innerConstructorThroughSubclass.kt")
public void testInnerConstructorThroughSubclass() throws Exception {