IR: check visibility when building fake overrides

This fixes the difference at least in the IR text test
testFakeOverridesForJavaNonStaticMembers. There's no fake override
created anymore for `packagePrivateMethod` in Test2.

 #KT-61366 Fixed
This commit is contained in:
Alexander Udalov
2023-09-14 17:57:57 +02:00
committed by Space Team
parent a23f2894b2
commit bb381e7aef
4 changed files with 40 additions and 20 deletions
@@ -216,12 +216,6 @@ class IrOverridingUtil(
return trueFakeOverrides.ifEmpty { customizedFakeOverrides }
}
private fun filterVisibleFakeOverrides(toFilter: Collection<IrOverridableMember>): Collection<IrOverridableMember> {
return toFilter.filter { member: IrOverridableMember ->
!DescriptorVisibilities.isPrivate(member.visibility) && member.visibility != DescriptorVisibilities.INVISIBLE_FAKE
}
}
private fun determineModalityForFakeOverride(
members: Collection<IrOverridableMember>,
current: IrClass
@@ -328,7 +322,7 @@ class IrOverridingUtil(
addedFakeOverrides: MutableList<IrOverridableMember>,
compatibilityMode: Boolean
) {
val effectiveOverridden = filterVisibleFakeOverrides(overridables)
val effectiveOverridden = overridables.filter { it.isVisibleInClass(currentClass) }
// The descriptor based algorithm goes further building invisible fakes here,
// but we don't use invisible fakes in IR
@@ -5,22 +5,17 @@
package org.jetbrains.kotlin.ir.overrides
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithVisibility
import org.jetbrains.kotlin.ir.declarations.IrOverridableDeclaration
import org.jetbrains.kotlin.ir.declarations.IrOverridableMember
import org.jetbrains.kotlin.ir.util.parentClassOrNull
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.types.getClass
import org.jetbrains.kotlin.ir.util.*
// The contents of this file is from VisibilityUtil.kt adapted to IR.
// TODO: The code would better be commonized for descriptors, ir and fir.
fun isVisibleForOverride(
@Suppress("UNUSED_PARAMETER") overriding: IrOverridableMember,
fromSuper: IrOverridableMember
): Boolean {
return !DescriptorVisibilities.isPrivate((fromSuper as IrDeclarationWithVisibility).visibility)
fun isVisibleForOverride(overriding: IrOverridableMember, fromSuper: IrOverridableMember): Boolean {
return fromSuper.isVisibleInClass(overriding.parentAsClass)
}
// Based on findMemberWithMaxVisibility from VisibilityUtil.kt.
fun findMemberWithMaxVisibility(members: Collection<IrOverridableMember>): IrOverridableMember {
assert(members.isNotEmpty())
@@ -60,3 +55,25 @@ fun IrDeclarationWithVisibility.isEffectivelyPrivate(): Boolean {
else -> true
}
}
internal fun IrOverridableMember.isVisibleInClass(klass: IrClass): Boolean {
if (DescriptorVisibilities.isPrivate(visibility) || visibility == DescriptorVisibilities.INVISIBLE_FAKE) return false
// OverridingUtil.isVisibleForOverride just calls DescriptorVisibilities.isVisible here. However, we can't use descriptors. Moreover,
// the current member's parent has already been reassigned to the current class (in OverridingUtil, it is still the original class where
// the member was declared at this point). So we load the original class from the dispatch receiver.
val dispatchReceiver = when (this) {
is IrSimpleFunction -> dispatchReceiverParameter
is IrProperty -> getter?.dispatchReceiverParameter
else -> error("Unsupported member: ${render()}")
} ?: error("Members without dispatch receiver are not possible here: ${render()} (klass=${klass.fqNameWhenAvailable}")
// Package-private Java members are only overridable within the same package.
val originalClass = dispatchReceiver.type.getClass()!!
if (!visibility.visibleFromPackage(klass.getPackageFragment().packageFqName, originalClass.getPackageFragment().packageFqName))
return false
// TODO (KT-61384): also check internal.
return true
}
@@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.java.JavaVisibilities;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
@@ -41,6 +42,11 @@ public class JavaDescriptorVisibilities {
) {
return areInSamePackage(what, from);
}
@Override
public boolean visibleFromPackage(@NotNull FqName fromPackage, @NotNull FqName myPackage) {
return fromPackage.equals(myPackage);
}
};
@NotNull
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.descriptors
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
abstract class DescriptorVisibility protected constructor() {
@@ -78,6 +79,8 @@ abstract class DescriptorVisibility protected constructor() {
// Should be overloaded in Java visibilities
fun customEffectiveVisibility(): EffectiveVisibility? = delegate.customEffectiveVisibility()
open fun visibleFromPackage(fromPackage: FqName, myPackage: FqName): Boolean = true
}
abstract class DelegatedDescriptorVisibility(override val delegate: Visibility) : DescriptorVisibility() {