K2: introduce platform-specific visibility checks for overrides + tests

Related to KT-53197
This commit is contained in:
pyos
2022-09-09 13:28:22 +02:00
committed by Space
parent 1ad2ec302b
commit 3a5d75fd22
19 changed files with 427 additions and 11 deletions
@@ -33872,6 +33872,18 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/tests/visibility/lackOfInvisibleSetterOfJavaClassInSamePackage.kt");
}
@Test
@TestMetadata("notOverridingInternal.kt")
public void testNotOverridingInternal() throws Exception {
runTest("compiler/testData/diagnostics/tests/visibility/notOverridingInternal.kt");
}
@Test
@TestMetadata("notOverridingPackagePrivate.kt")
public void testNotOverridingPackagePrivate() throws Exception {
runTest("compiler/testData/diagnostics/tests/visibility/notOverridingPackagePrivate.kt");
}
@Test
@TestMetadata("overrideOfMemberInPackagePrivateClass.kt")
public void testOverrideOfMemberInPackagePrivateClass() throws Exception {
@@ -33872,6 +33872,18 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/visibility/lackOfInvisibleSetterOfJavaClassInSamePackage.kt");
}
@Test
@TestMetadata("notOverridingInternal.kt")
public void testNotOverridingInternal() throws Exception {
runTest("compiler/testData/diagnostics/tests/visibility/notOverridingInternal.kt");
}
@Test
@TestMetadata("notOverridingPackagePrivate.kt")
public void testNotOverridingPackagePrivate() throws Exception {
runTest("compiler/testData/diagnostics/tests/visibility/notOverridingPackagePrivate.kt");
}
@Test
@TestMetadata("overrideOfMemberInPackagePrivateClass.kt")
public void testOverrideOfMemberInPackagePrivateClass() throws Exception {
@@ -33872,6 +33872,18 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/visibility/lackOfInvisibleSetterOfJavaClassInSamePackage.kt");
}
@Test
@TestMetadata("notOverridingInternal.kt")
public void testNotOverridingInternal() throws Exception {
runTest("compiler/testData/diagnostics/tests/visibility/notOverridingInternal.kt");
}
@Test
@TestMetadata("notOverridingPackagePrivate.kt")
public void testNotOverridingPackagePrivate() throws Exception {
runTest("compiler/testData/diagnostics/tests/visibility/notOverridingPackagePrivate.kt");
}
@Test
@TestMetadata("overrideOfMemberInPackagePrivateClass.kt")
public void testOverrideOfMemberInPackagePrivateClass() throws Exception {
@@ -2596,6 +2596,12 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest {
runTest("compiler/testData/ir/irText/firProblems/InnerClassInAnonymous.kt");
}
@Test
@TestMetadata("internalPotentialOverride.kt")
public void testInternalPotentialOverride() throws Exception {
runTest("compiler/testData/ir/irText/firProblems/internalPotentialOverride.kt");
}
@Test
@TestMetadata("kt19251.kt")
public void testKt19251() throws Exception {
@@ -2596,6 +2596,12 @@ public class LightTreeFir2IrTextTestGenerated extends AbstractLightTreeFir2IrTex
runTest("compiler/testData/ir/irText/firProblems/InnerClassInAnonymous.kt");
}
@Test
@TestMetadata("internalPotentialOverride.kt")
public void testInternalPotentialOverride() throws Exception {
runTest("compiler/testData/ir/irText/firProblems/internalPotentialOverride.kt");
}
@Test
@TestMetadata("kt19251.kt")
public void testKt19251() throws Exception {
@@ -17,6 +17,7 @@ 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.name.FqName
@NoMutableState
object FirJavaVisibilityChecker : FirVisibilityChecker() {
@@ -50,17 +51,22 @@ object FirJavaVisibilityChecker : FirVisibilityChecker() {
}
}
JavaVisibilities.PackageVisibility -> {
if (symbol.packageFqName() == useSiteFile.packageFqName) {
true
} else if (symbol.fir is FirSyntheticPropertyAccessor) {
symbol.getOwnerLookupTag()?.classId?.packageFqName == useSiteFile.packageFqName
} else {
false
}
}
JavaVisibilities.PackageVisibility -> symbol.isInPackage(useSiteFile.packageFqName)
else -> true
}
}
override fun platformOverrideVisibilityCheck(
session: FirSession,
candidateInDerivedClass: FirBasedSymbol<*>,
symbolInBaseClass: FirBasedSymbol<*>,
visibilityInBaseClass: Visibility,
): Boolean = when (visibilityInBaseClass) {
JavaVisibilities.ProtectedAndPackage, JavaVisibilities.ProtectedStaticVisibility -> true
JavaVisibilities.PackageVisibility -> symbolInBaseClass.isInPackage(candidateInDerivedClass.packageFqName())
else -> true
}
private fun FirBasedSymbol<*>.isInPackage(expected: FqName): Boolean =
packageFqName() == expected || (fir is FirSyntheticPropertyAccessor && getOwnerLookupTag()?.classId?.packageFqName == expected)
}
@@ -62,6 +62,15 @@ abstract class FirVisibilityChecker : FirSessionComponent {
): Boolean {
return true
}
override fun platformOverrideVisibilityCheck(
session: FirSession,
candidateInDerivedClass: FirBasedSymbol<*>,
symbolInBaseClass: FirBasedSymbol<*>,
visibilityInBaseClass: Visibility,
): Boolean {
return true
}
}
fun isVisible(
@@ -107,6 +116,24 @@ abstract class FirVisibilityChecker : FirSessionComponent {
}
}
fun isVisibleForOverriding(
session: FirSession,
candidateInDerivedClass: FirMemberDeclaration,
candidateInBaseClass: FirMemberDeclaration
): Boolean = when (candidateInBaseClass.visibility) {
Visibilities.Internal -> {
candidateInBaseClass.moduleData == candidateInDerivedClass.moduleData ||
(candidateInDerivedClass.moduleData == session.moduleData &&
session.moduleVisibilityChecker?.isInFriendModule(candidateInBaseClass) == true)
}
Visibilities.Private, Visibilities.PrivateToThis -> false
Visibilities.Protected -> true
else -> platformOverrideVisibilityCheck(
session, candidateInDerivedClass.symbol, candidateInBaseClass.symbol, candidateInBaseClass.visibility
)
}
private fun FirMemberDeclaration.containingNonLocalClass(
session: FirSession,
dispatchReceiverValue: ReceiverValue?
@@ -226,6 +253,13 @@ abstract class FirVisibilityChecker : FirSessionComponent {
supertypeSupplier: SupertypeSupplier
): Boolean
protected abstract fun platformOverrideVisibilityCheck(
session: FirSession,
candidateInDerivedClass: FirBasedSymbol<*>,
symbolInBaseClass: FirBasedSymbol<*>,
visibilityInBaseClass: Visibility,
): Boolean
private fun canSeePrivateMemberOf(
symbol: FirBasedSymbol<*>,
containingDeclarationOfUseSite: List<FirDeclaration>,
@@ -357,7 +391,9 @@ abstract class FirVisibilityChecker : FirSessionComponent {
stubTypesEqualToAnything = false
)
if (AbstractTypeChecker.isSubtypeOf(
typeCheckerState, dispatchReceiverType.fullyExpandedType(session), containingUseSiteClass.symbol.constructStarProjectedType()
typeCheckerState,
dispatchReceiverType.fullyExpandedType(session),
containingUseSiteClass.symbol.constructStarProjectedType()
)
) {
return true
@@ -0,0 +1,24 @@
// FIR_IDENTICAL
// MODULE: base
// FILE: Base.kt
package base
abstract class Base {
fun foo() = internalFoo()
internal fun internalFoo() {}
}
// MODULE: impl(base)
// FILE: Impl.kt
package impl
import base.*
class Impl : Base() {
fun internalFoo() { /*not an override*/ }
}
fun foo() {
Impl().foo()
Impl().internalFoo()
}
@@ -0,0 +1,30 @@
// -- Module: <base> --
package
package base {
public abstract class Base {
public constructor Base()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
internal final fun internalFoo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
// -- Module: <impl> --
package
package impl {
public fun foo(): kotlin.Unit
public final class Impl : base.Base {
public constructor Impl()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final override /*1*/ /*fake_override*/ fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final fun internalFoo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
@@ -0,0 +1,23 @@
// FILE: base/Base.java
package base;
public abstract class Base {
public void foo() {
packagePrivateFoo();
}
/* package-private */ void packagePrivateFoo() {};
}
// FILE: Impl.kt
package impl
import base.*
class Impl : Base() {
fun packagePrivateFoo() { /*not an override*/ }
}
fun foo() {
Impl().foo()
Impl().<!INVISIBLE_REFERENCE!>packagePrivateFoo<!>()
}
@@ -0,0 +1,23 @@
// FILE: base/Base.java
package base;
public abstract class Base {
public void foo() {
packagePrivateFoo();
}
/* package-private */ void packagePrivateFoo() {};
}
// FILE: Impl.kt
package impl
import base.*
class Impl : Base() {
fun packagePrivateFoo() { /*not an override*/ }
}
fun foo() {
Impl().foo()
Impl().packagePrivateFoo()
}
@@ -0,0 +1,26 @@
package
package base {
public abstract class Base {
public constructor Base()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public/*package*/ open fun packagePrivateFoo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
package impl {
public fun foo(): kotlin.Unit
public final class Impl : base.Base {
public constructor Impl()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final fun packagePrivateFoo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
@@ -0,0 +1,54 @@
Module: m1
FILE fqName:<root> fileName:/A.kt
CLASS CLASS name:A modality:OPEN visibility:public superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.A
CONSTRUCTOR visibility:public <> () returnType:<root>.A [primary]
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any'
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:A modality:OPEN visibility:public superTypes:[kotlin.Any]'
FUN name:foo visibility:internal modality:OPEN <> ($this:<root>.A) returnType:kotlin.Int
$this: VALUE_PARAMETER name:<this> type:<root>.A
BLOCK_BODY
RETURN type=kotlin.Nothing from='internal open fun foo (): kotlin.Int declared in <root>.A'
CONST Int type=kotlin.Int value=1
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
overridden:
public open fun hashCode (): kotlin.Int declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
overridden:
public open fun toString (): kotlin.String declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
Module: m2
FILE fqName:<root> fileName:/B.kt
CLASS CLASS name:B modality:FINAL visibility:public superTypes:[<root>.A]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.B
CONSTRUCTOR visibility:public <> () returnType:<root>.B [primary]
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in <root>.A'
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:B modality:FINAL visibility:public superTypes:[<root>.A]'
FUN name:foo visibility:internal modality:FINAL <> ($this:<root>.B) returnType:kotlin.String
overridden:
internal open fun foo (): kotlin.Int declared in <root>.A
$this: VALUE_PARAMETER name:<this> type:<root>.B
BLOCK_BODY
RETURN type=kotlin.Nothing from='internal final fun foo (): kotlin.String declared in <root>.B'
CONST String type=kotlin.String value="OK"
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean [fake_override,operator] declared in <root>.A
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
overridden:
public open fun hashCode (): kotlin.Int [fake_override] declared in <root>.A
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
overridden:
public open fun toString (): kotlin.String [fake_override] declared in <root>.A
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
@@ -0,0 +1,31 @@
// MODULE: m1
// FILE: A.kt
open class A {
constructor() /* primary */ {
super/*Any*/()
/* <init>() */
}
internal open fun foo(): Int {
return 1
}
}
// MODULE: m2
// FILE: B.kt
class B : A {
constructor() /* primary */ {
super/*A*/()
/* <init>() */
}
internal override fun foo(): String {
return "OK"
}
}
@@ -0,0 +1,52 @@
Module: m1
FILE fqName:<root> fileName:/A.kt
CLASS CLASS name:A modality:OPEN visibility:public superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.A
CONSTRUCTOR visibility:public <> () returnType:<root>.A [primary]
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any'
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:A modality:OPEN visibility:public superTypes:[kotlin.Any]'
FUN name:foo visibility:internal modality:OPEN <> ($this:<root>.A) returnType:kotlin.Int
$this: VALUE_PARAMETER name:<this> type:<root>.A
BLOCK_BODY
RETURN type=kotlin.Nothing from='internal open fun foo (): kotlin.Int declared in <root>.A'
CONST Int type=kotlin.Int value=1
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
overridden:
public open fun hashCode (): kotlin.Int declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
overridden:
public open fun toString (): kotlin.String declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
Module: m2
FILE fqName:<root> fileName:/B.kt
CLASS CLASS name:B modality:FINAL visibility:public superTypes:[<root>.A]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.B
CONSTRUCTOR visibility:public <> () returnType:<root>.B [primary]
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in <root>.A'
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:B modality:FINAL visibility:public superTypes:[<root>.A]'
FUN name:foo visibility:public modality:FINAL <> ($this:<root>.B) returnType:kotlin.String
$this: VALUE_PARAMETER name:<this> type:<root>.B
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun foo (): kotlin.String declared in <root>.B'
CONST String type=kotlin.String value="OK"
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean [fake_override,operator] declared in <root>.A
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
overridden:
public open fun hashCode (): kotlin.Int [fake_override] declared in <root>.A
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
overridden:
public open fun toString (): kotlin.String [fake_override] declared in <root>.A
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
@@ -0,0 +1,14 @@
// TARGET_BACKEND: JVM_IR
// MODULE: m1
// FILE: A.kt
open class A {
internal open fun foo() : Int = 1
}
// MODULE: m2(m1)
// FILE: B.kt
class B : A() {
fun foo() : String = "OK"
}
@@ -0,0 +1,31 @@
// MODULE: m1
// FILE: A.kt
open class A {
constructor() /* primary */ {
super/*Any*/()
/* <init>() */
}
internal open fun foo(): Int {
return 1
}
}
// MODULE: m2
// FILE: B.kt
class B : A {
constructor() /* primary */ {
super/*A*/()
/* <init>() */
}
fun foo(): String {
return "OK"
}
}
@@ -33962,6 +33962,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/visibility/lackOfInvisibleSetterOfJavaClassInSamePackage.kt");
}
@Test
@TestMetadata("notOverridingInternal.kt")
public void testNotOverridingInternal() throws Exception {
runTest("compiler/testData/diagnostics/tests/visibility/notOverridingInternal.kt");
}
@Test
@TestMetadata("notOverridingPackagePrivate.kt")
public void testNotOverridingPackagePrivate() throws Exception {
runTest("compiler/testData/diagnostics/tests/visibility/notOverridingPackagePrivate.kt");
}
@Test
@TestMetadata("overrideOfMemberInPackagePrivateClass.kt")
public void testOverrideOfMemberInPackagePrivateClass() throws Exception {
@@ -2596,6 +2596,12 @@ public class IrTextTestGenerated extends AbstractIrTextTest {
runTest("compiler/testData/ir/irText/firProblems/InnerClassInAnonymous.kt");
}
@Test
@TestMetadata("internalPotentialOverride.kt")
public void testInternalPotentialOverride() throws Exception {
runTest("compiler/testData/ir/irText/firProblems/internalPotentialOverride.kt");
}
@Test
@TestMetadata("kt19251.kt")
public void testKt19251() throws Exception {