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:
committed by
Space Team
parent
a23f2894b2
commit
bb381e7aef
@@ -216,12 +216,6 @@ class IrOverridingUtil(
|
|||||||
return trueFakeOverrides.ifEmpty { customizedFakeOverrides }
|
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(
|
private fun determineModalityForFakeOverride(
|
||||||
members: Collection<IrOverridableMember>,
|
members: Collection<IrOverridableMember>,
|
||||||
current: IrClass
|
current: IrClass
|
||||||
@@ -328,7 +322,7 @@ class IrOverridingUtil(
|
|||||||
addedFakeOverrides: MutableList<IrOverridableMember>,
|
addedFakeOverrides: MutableList<IrOverridableMember>,
|
||||||
compatibilityMode: Boolean
|
compatibilityMode: Boolean
|
||||||
) {
|
) {
|
||||||
val effectiveOverridden = filterVisibleFakeOverrides(overridables)
|
val effectiveOverridden = overridables.filter { it.isVisibleInClass(currentClass) }
|
||||||
|
|
||||||
// The descriptor based algorithm goes further building invisible fakes here,
|
// The descriptor based algorithm goes further building invisible fakes here,
|
||||||
// but we don't use invisible fakes in IR
|
// but we don't use invisible fakes in IR
|
||||||
|
|||||||
@@ -5,22 +5,17 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.overrides
|
package org.jetbrains.kotlin.ir.overrides
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithVisibility
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrOverridableDeclaration
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrOverridableMember
|
import org.jetbrains.kotlin.ir.types.getClass
|
||||||
import org.jetbrains.kotlin.ir.util.parentClassOrNull
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
|
|
||||||
// The contents of this file is from VisibilityUtil.kt adapted to IR.
|
fun isVisibleForOverride(overriding: IrOverridableMember, fromSuper: IrOverridableMember): Boolean {
|
||||||
// TODO: The code would better be commonized for descriptors, ir and fir.
|
return fromSuper.isVisibleInClass(overriding.parentAsClass)
|
||||||
|
|
||||||
fun isVisibleForOverride(
|
|
||||||
@Suppress("UNUSED_PARAMETER") overriding: IrOverridableMember,
|
|
||||||
fromSuper: IrOverridableMember
|
|
||||||
): Boolean {
|
|
||||||
return !DescriptorVisibilities.isPrivate((fromSuper as IrDeclarationWithVisibility).visibility)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Based on findMemberWithMaxVisibility from VisibilityUtil.kt.
|
||||||
fun findMemberWithMaxVisibility(members: Collection<IrOverridableMember>): IrOverridableMember {
|
fun findMemberWithMaxVisibility(members: Collection<IrOverridableMember>): IrOverridableMember {
|
||||||
assert(members.isNotEmpty())
|
assert(members.isNotEmpty())
|
||||||
|
|
||||||
@@ -60,3 +55,25 @@ fun IrDeclarationWithVisibility.isEffectivelyPrivate(): Boolean {
|
|||||||
else -> true
|
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
|
||||||
|
}
|
||||||
|
|||||||
+6
@@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.descriptors.java.JavaVisibilities;
|
import org.jetbrains.kotlin.descriptors.java.JavaVisibilities;
|
||||||
|
import org.jetbrains.kotlin.name.FqName;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||||
|
|
||||||
@@ -41,6 +42,11 @@ public class JavaDescriptorVisibilities {
|
|||||||
) {
|
) {
|
||||||
return areInSamePackage(what, from);
|
return areInSamePackage(what, from);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visibleFromPackage(@NotNull FqName fromPackage, @NotNull FqName myPackage) {
|
||||||
|
return fromPackage.equals(myPackage);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.descriptors
|
package org.jetbrains.kotlin.descriptors
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||||
|
|
||||||
abstract class DescriptorVisibility protected constructor() {
|
abstract class DescriptorVisibility protected constructor() {
|
||||||
@@ -78,6 +79,8 @@ abstract class DescriptorVisibility protected constructor() {
|
|||||||
|
|
||||||
// Should be overloaded in Java visibilities
|
// Should be overloaded in Java visibilities
|
||||||
fun customEffectiveVisibility(): EffectiveVisibility? = delegate.customEffectiveVisibility()
|
fun customEffectiveVisibility(): EffectiveVisibility? = delegate.customEffectiveVisibility()
|
||||||
|
|
||||||
|
open fun visibleFromPackage(fromPackage: FqName, myPackage: FqName): Boolean = true
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class DelegatedDescriptorVisibility(override val delegate: Visibility) : DescriptorVisibility() {
|
abstract class DelegatedDescriptorVisibility(override val delegate: Visibility) : DescriptorVisibility() {
|
||||||
|
|||||||
Reference in New Issue
Block a user