diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/overrides/IrOverridingUtil.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/overrides/IrOverridingUtil.kt index 14acd768ee5..01ed3606867 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/overrides/IrOverridingUtil.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/overrides/IrOverridingUtil.kt @@ -216,12 +216,6 @@ class IrOverridingUtil( return trueFakeOverrides.ifEmpty { customizedFakeOverrides } } - private fun filterVisibleFakeOverrides(toFilter: Collection): Collection { - return toFilter.filter { member: IrOverridableMember -> - !DescriptorVisibilities.isPrivate(member.visibility) && member.visibility != DescriptorVisibilities.INVISIBLE_FAKE - } - } - private fun determineModalityForFakeOverride( members: Collection, current: IrClass @@ -328,7 +322,7 @@ class IrOverridingUtil( addedFakeOverrides: MutableList, 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 diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/overrides/IrVisibilityUtil.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/overrides/IrVisibilityUtil.kt index 40d85739822..9b8ea9b39e3 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/overrides/IrVisibilityUtil.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/overrides/IrVisibilityUtil.kt @@ -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 { 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 +} diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/JavaDescriptorVisibilities.java b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/JavaDescriptorVisibilities.java index bdd4a26c01f..5e2789c58e8 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/JavaDescriptorVisibilities.java +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/JavaDescriptorVisibilities.java @@ -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 diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/DescriptorVisibility.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/DescriptorVisibility.kt index b4497183b96..9168046d3be 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/DescriptorVisibility.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/DescriptorVisibility.kt @@ -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() {