K2: filter invisible overridden in status resolver & FIR2IR

Related to KT-53197
This commit is contained in:
Mikhail Glukhikh
2022-09-19 17:53:29 +02:00
committed by Space
parent 3a5d75fd22
commit bcd7a531b9
9 changed files with 57 additions and 136 deletions
@@ -17,7 +17,6 @@ import org.jetbrains.kotlin.fir.declarations.builder.buildFile
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
import org.jetbrains.kotlin.fir.declarations.utils.isInline import org.jetbrains.kotlin.fir.declarations.utils.isInline
import org.jetbrains.kotlin.fir.declarations.utils.isJava import org.jetbrains.kotlin.fir.declarations.utils.isJava
import org.jetbrains.kotlin.fir.declarations.utils.visibility
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.extensions.FirExtensionApiInternals import org.jetbrains.kotlin.fir.extensions.FirExtensionApiInternals
@@ -370,11 +369,14 @@ internal fun FirSimpleFunction.processOverriddenFunctionSymbols(
) { ) {
val scope = containingClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true) val scope = containingClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true)
scope.processFunctionsByName(name) {} scope.processFunctionsByName(name) {}
scope.processOverriddenFunctionsFromSuperClasses(symbol, containingClass) { scope.processOverriddenFunctionsFromSuperClasses(symbol, containingClass) { overriddenSymbol ->
if (it.fir.visibility == Visibilities.Private) { if (!session.visibilityChecker.isVisibleForOverriding(
session, candidateInDerivedClass = symbol.fir, candidateInBaseClass = overriddenSymbol.fir
)
) {
return@processOverriddenFunctionsFromSuperClasses ProcessorAction.NEXT return@processOverriddenFunctionsFromSuperClasses ProcessorAction.NEXT
} }
processor(it) processor(overriddenSymbol)
ProcessorAction.NEXT ProcessorAction.NEXT
} }
@@ -442,11 +444,14 @@ internal fun FirProperty.processOverriddenPropertySymbols(
val scope = containingClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true) val scope = containingClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true)
scope.processPropertiesByName(name) {} scope.processPropertiesByName(name) {}
val overriddenSet = mutableSetOf<IrPropertySymbol>() val overriddenSet = mutableSetOf<IrPropertySymbol>()
scope.processOverriddenPropertiesFromSuperClasses(symbol, containingClass) { scope.processOverriddenPropertiesFromSuperClasses(symbol, containingClass) { overriddenSymbol ->
if (it.fir.visibility == Visibilities.Private) { if (!session.visibilityChecker.isVisibleForOverriding(
session, candidateInDerivedClass = symbol.fir, candidateInBaseClass = overriddenSymbol.fir
)
) {
return@processOverriddenPropertiesFromSuperClasses ProcessorAction.NEXT return@processOverriddenPropertiesFromSuperClasses ProcessorAction.NEXT
} }
processor(it) processor(overriddenSymbol)
ProcessorAction.NEXT ProcessorAction.NEXT
} }
@@ -475,15 +480,20 @@ internal fun FirProperty.generateOverriddenAccessorSymbols(containingClass: FirC
val overriddenSet = mutableSetOf<IrSimpleFunctionSymbol>() val overriddenSet = mutableSetOf<IrSimpleFunctionSymbol>()
val superClasses = containingClass.getSuperTypesAsIrClasses() ?: return emptyList() val superClasses = containingClass.getSuperTypesAsIrClasses() ?: return emptyList()
scope.processOverriddenPropertiesFromSuperClasses(symbol, containingClass) { scope.processOverriddenPropertiesFromSuperClasses(symbol, containingClass) { overriddenSymbol ->
if (it.fir.visibility == Visibilities.Private) { if (!session.visibilityChecker.isVisibleForOverriding(
session, candidateInDerivedClass = symbol.fir, candidateInBaseClass = overriddenSymbol.fir
)
) {
return@processOverriddenPropertiesFromSuperClasses ProcessorAction.NEXT return@processOverriddenPropertiesFromSuperClasses ProcessorAction.NEXT
} }
for (overriddenProperty in fakeOverrideGenerator.getOverriddenSymbolsInSupertypes(it, superClasses)) { for (overriddenIrPropertySymbol in fakeOverrideGenerator.getOverriddenSymbolsInSupertypes(overriddenSymbol, superClasses)) {
val overriddenAccessor = if (isGetter) overriddenProperty.owner.getter?.symbol else overriddenProperty.owner.setter?.symbol val overriddenIrAccessorSymbol =
if (overriddenAccessor != null) { if (isGetter) overriddenIrPropertySymbol.owner.getter?.symbol
overriddenSet += overriddenAccessor else overriddenIrPropertySymbol.owner.setter?.symbol
if (overriddenIrAccessorSymbol != null) {
overriddenSet += overriddenIrAccessorSymbol
} }
} }
ProcessorAction.NEXT ProcessorAction.NEXT
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.fir.backend.generators package org.jetbrains.kotlin.fir.backend.generators
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
import org.jetbrains.kotlin.fir.backend.Fir2IrConversionScope import org.jetbrains.kotlin.fir.backend.Fir2IrConversionScope
@@ -88,7 +87,6 @@ class FakeOverrideGenerator(
return result return result
} }
@OptIn(ExperimentalStdlibApi::class)
fun generateFakeOverridesForName( fun generateFakeOverridesForName(
irClass: IrClass, irClass: IrClass,
name: Name, name: Name,
@@ -205,7 +203,7 @@ class FakeOverrideGenerator(
// But they are treated differently in IR (real declarations have already been declared before) and such methods are present among realDeclarationSymbols // But they are treated differently in IR (real declarations have already been declared before) and such methods are present among realDeclarationSymbols
if (originalSymbol in realDeclarationSymbols) return if (originalSymbol in realDeclarationSymbols) return
if (originalDeclaration.visibility == Visibilities.Private) return if (!session.visibilityChecker.isVisibleForOverriding(session, klass.moduleData, klass.symbol, originalDeclaration)) return
val origin = IrDeclarationOrigin.FAKE_OVERRIDE val origin = IrDeclarationOrigin.FAKE_OVERRIDE
val baseSymbol = originalSymbol.unwrapSubstitutionAndIntersectionOverrides() as S val baseSymbol = originalSymbol.unwrapSubstitutionAndIntersectionOverrides() as S
@@ -120,17 +120,24 @@ abstract class FirVisibilityChecker : FirSessionComponent {
session: FirSession, session: FirSession,
candidateInDerivedClass: FirMemberDeclaration, candidateInDerivedClass: FirMemberDeclaration,
candidateInBaseClass: FirMemberDeclaration candidateInBaseClass: FirMemberDeclaration
): Boolean = isVisibleForOverriding(session, candidateInDerivedClass.moduleData, candidateInDerivedClass.symbol, candidateInBaseClass)
fun isVisibleForOverriding(
session: FirSession,
derivedClassModuleData: FirModuleData,
symbolFromDerivedClass: FirBasedSymbol<*>,
candidateInBaseClass: FirMemberDeclaration,
): Boolean = when (candidateInBaseClass.visibility) { ): Boolean = when (candidateInBaseClass.visibility) {
Visibilities.Internal -> { Visibilities.Internal -> {
candidateInBaseClass.moduleData == candidateInDerivedClass.moduleData || candidateInBaseClass.moduleData == derivedClassModuleData ||
(candidateInDerivedClass.moduleData == session.moduleData && (derivedClassModuleData == session.moduleData &&
session.moduleVisibilityChecker?.isInFriendModule(candidateInBaseClass) == true) session.moduleVisibilityChecker?.isInFriendModule(candidateInBaseClass) == true)
} }
Visibilities.Private, Visibilities.PrivateToThis -> false Visibilities.Private, Visibilities.PrivateToThis -> false
Visibilities.Protected -> true Visibilities.Protected -> true
else -> platformOverrideVisibilityCheck( else -> platformOverrideVisibilityCheck(
session, candidateInDerivedClass.symbol, candidateInBaseClass.symbol, candidateInBaseClass.visibility session, symbolFromDerivedClass, candidateInBaseClass.symbol, candidateInBaseClass.visibility
) )
} }
@@ -93,8 +93,13 @@ class FirStatusResolver(
return buildList { return buildList {
scope.processPropertiesByName(property.name) {} scope.processPropertiesByName(property.name) {}
scope.processDirectOverriddenPropertiesWithBaseScope(property.symbol) { symbol, _ -> scope.processDirectOverriddenPropertiesWithBaseScope(property.symbol) { overriddenSymbol, _ ->
this += symbol.fir if (session.visibilityChecker.isVisibleForOverriding(
session, candidateInDerivedClass = property, candidateInBaseClass = overriddenSymbol.fir
)
) {
this += overriddenSymbol.fir
}
ProcessorAction.NEXT ProcessorAction.NEXT
} }
} }
@@ -129,7 +134,12 @@ class FirStatusResolver(
val symbol = function.symbol val symbol = function.symbol
scope.processFunctionsByName(function.name) {} scope.processFunctionsByName(function.name) {}
scope.processDirectOverriddenFunctionsWithBaseScope(symbol) { overriddenSymbol, _ -> scope.processDirectOverriddenFunctionsWithBaseScope(symbol) { overriddenSymbol, _ ->
this += overriddenSymbol.fir if (session.visibilityChecker.isVisibleForOverriding(
session, candidateInDerivedClass = function, candidateInBaseClass = overriddenSymbol.fir
)
) {
this += overriddenSymbol.fir
}
ProcessorAction.NEXT ProcessorAction.NEXT
} }
}.mapNotNull { }.mapNotNull {
@@ -215,15 +225,18 @@ class FirStatusResolver(
isLocal -> Visibilities.Local isLocal -> Visibilities.Local
else -> resolveVisibility(declaration, containingClass, containingProperty, overriddenStatuses) else -> resolveVisibility(declaration, containingClass, containingProperty, overriddenStatuses)
} }
Visibilities.Private -> when { Visibilities.Private -> when {
declaration is FirPropertyAccessor -> if (containingProperty?.visibility == Visibilities.PrivateToThis) { declaration is FirPropertyAccessor -> if (containingProperty?.visibility == Visibilities.PrivateToThis) {
Visibilities.PrivateToThis Visibilities.PrivateToThis
} else { } else {
Visibilities.Private Visibilities.Private
} }
isPrivateToThis(declaration, containingClass) -> Visibilities.PrivateToThis isPrivateToThis(declaration, containingClass) -> Visibilities.PrivateToThis
else -> Visibilities.Private else -> Visibilities.Private
} }
else -> status.visibility else -> status.visibility
} }
@@ -375,14 +388,12 @@ class FirStatusResolver(
containingClass == null -> Modality.FINAL containingClass == null -> Modality.FINAL
containingClass.classKind == ClassKind.INTERFACE -> { containingClass.classKind == ClassKind.INTERFACE -> {
when { when {
declaration.visibility == Visibilities.Private -> declaration.visibility == Visibilities.Private -> Modality.FINAL
Modality.FINAL !declaration.hasOwnBodyOrAccessorBody() -> Modality.ABSTRACT
!declaration.hasOwnBodyOrAccessorBody() -> else -> Modality.OPEN
Modality.ABSTRACT
else ->
Modality.OPEN
} }
} }
else -> { else -> {
if (declaration.isOverride && if (declaration.isOverride &&
(containingClass.modality != Modality.FINAL || containingClass.classKind == ClassKind.ENUM_CLASS) (containingClass.modality != Modality.FINAL || containingClass.classKind == ClassKind.ENUM_CLASS)
@@ -394,6 +405,7 @@ class FirStatusResolver(
} }
} }
} }
else -> Modality.FINAL else -> Modality.FINAL
} }
@@ -1,23 +0,0 @@
// 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<!>()
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// FILE: base/Base.java // FILE: base/Base.java
package base; package base;
@@ -1,54 +0,0 @@
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
@@ -1,31 +0,0 @@
// 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"
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// TARGET_BACKEND: JVM_IR // TARGET_BACKEND: JVM_IR
// MODULE: m1 // MODULE: m1
// FILE: A.kt // FILE: A.kt