JVM_IR KT-45998 protected companion object member accessors with indy
This commit is contained in:
committed by
TeamCityServer
parent
9a4a39e680
commit
7f4da93cc3
+9
-3
@@ -20960,9 +20960,15 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("protectedSuperclassCompanionObjectMember.kt")
|
||||
public void testProtectedSuperclassCompanionObjectMember() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/protectedSuperclassCompanionObjectMember.kt");
|
||||
@TestMetadata("protectedCompanionObjectStaticMember.kt")
|
||||
public void testProtectedCompanionObjectStaticMember() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/protectedCompanionObjectStaticMember.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("protectedMember.kt")
|
||||
public void testProtectedMember() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/protectedMember.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+42
-13
@@ -178,7 +178,8 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
|
||||
?: throw AssertionError("'implMethodReference' is expected to be 'IrFunctionReference': ${call.dump()}")
|
||||
val implFunSymbol = implFunRef.symbol
|
||||
|
||||
if (implFunSymbol.isAccessible(false, thisSymbol)) return call
|
||||
if (implFunSymbol.isAccessibleFromSyntheticProxy(thisSymbol))
|
||||
return call
|
||||
|
||||
val accessorSymbol = createAccessor(implFunSymbol, implFunRef.dispatchReceiver?.type, null)
|
||||
val accessorFun = accessorSymbol.owner
|
||||
@@ -212,6 +213,23 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
|
||||
return call
|
||||
}
|
||||
|
||||
private fun IrFunctionSymbol.isAccessibleFromSyntheticProxy(thisSymbol: IrClassSymbol?): Boolean {
|
||||
if (!isAccessible(false, thisSymbol))
|
||||
return false
|
||||
|
||||
if (owner.visibility != DescriptorVisibilities.PROTECTED &&
|
||||
owner.visibility != JavaDescriptorVisibilities.PROTECTED_STATIC_VISIBILITY
|
||||
) {
|
||||
return true
|
||||
}
|
||||
|
||||
// We have a protected member.
|
||||
// It is accessible from a synthetic proxy class (created by LambdaMetafactory)
|
||||
// if it belongs to the current class.
|
||||
val outerClassInfo = getOuterClassInfo() ?: return false
|
||||
return outerClassInfo.outerClass == owner.parentAsClass
|
||||
}
|
||||
|
||||
override fun visitGetField(expression: IrGetField): IrExpression {
|
||||
val dispatchReceiverType = expression.receiver?.type
|
||||
return super.visitExpression(
|
||||
@@ -713,6 +731,25 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
|
||||
// If local variables are accessible by Kotlin rules, they also are by Java rules.
|
||||
val ownerClass = declaration.parent as? IrClass ?: return true
|
||||
|
||||
val outerClassInfo = getOuterClassInfo() ?: return false
|
||||
val outerClass = outerClassInfo.outerClass
|
||||
val throughCrossinlineLambda = outerClassInfo.throughCrossinlineLambda
|
||||
|
||||
val samePackage = ownerClass.getPackageFragment()?.fqName == outerClass.getPackageFragment()?.fqName
|
||||
val fromSubclassOfReceiversClass = !throughCrossinlineLambda &&
|
||||
outerClass.isSubclassOf(ownerClass) &&
|
||||
(thisObjReference == null || outerClass.symbol.isSubtypeOfClass(thisObjReference))
|
||||
return when {
|
||||
declaration.visibility.isPrivate && (throughCrossinlineLambda || ownerClass != outerClass) -> false
|
||||
declaration.visibility.isProtected && !samePackage && !fromSubclassOfReceiversClass -> false
|
||||
withSuper && !fromSubclassOfReceiversClass -> false
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
|
||||
private class OuterClassInfo(val outerClass: IrClass, val throughCrossinlineLambda: Boolean)
|
||||
|
||||
private fun getOuterClassInfo(): OuterClassInfo? {
|
||||
var context = currentScope!!.irElement as IrDeclaration
|
||||
var throughCrossinlineLambda = false
|
||||
while (context !is IrClass) {
|
||||
@@ -727,21 +764,13 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
|
||||
// inlined into a different class, e.g. a callable reference. For protected inline functions
|
||||
// calling methods on `super` we also need an accessor to satisfy INVOKESPECIAL constraints.
|
||||
// TODO scan nested classes for calls to private inline functions?
|
||||
return false
|
||||
return null
|
||||
} else {
|
||||
context = context.parent as? IrDeclaration ?: return false
|
||||
context = context.parent as? IrDeclaration
|
||||
?: return null
|
||||
}
|
||||
}
|
||||
|
||||
val samePackage = ownerClass.getPackageFragment()?.fqName == context.getPackageFragment()?.fqName
|
||||
val fromSubclassOfReceiversClass = !throughCrossinlineLambda &&
|
||||
context.isSubclassOf(ownerClass) && (thisObjReference == null || context.symbol.isSubtypeOfClass(thisObjReference))
|
||||
return when {
|
||||
declaration.visibility.isPrivate && (throughCrossinlineLambda || ownerClass != context) -> false
|
||||
declaration.visibility.isProtected && !samePackage && !fromSubclassOfReceiversClass -> false
|
||||
withSuper && !fromSubclassOfReceiversClass -> false
|
||||
else -> true
|
||||
}
|
||||
return OuterClassInfo(context, throughCrossinlineLambda)
|
||||
}
|
||||
|
||||
// monitorEnter/monitorExit are the only functions which are accessed "illegally" (see kotlin/util/Synchronized.kt).
|
||||
|
||||
+10
-2
@@ -8,6 +8,7 @@
|
||||
|
||||
// CHECK_BYTECODE_TEXT
|
||||
// 1 java/lang/invoke/LambdaMetafactory
|
||||
// 1 c2/C2\.access\$test\$s[0-9]+\(\)Ljava/lang/String\;
|
||||
|
||||
// FILE: test.kt
|
||||
import c2.*
|
||||
@@ -29,8 +30,15 @@ open class C1 {
|
||||
package c2
|
||||
|
||||
import c1.*
|
||||
import java.util.function.Supplier
|
||||
import j.*
|
||||
|
||||
class C2 : C1() {
|
||||
fun supplier() = Supplier<String>(::test)
|
||||
fun supplier() = J(::test)
|
||||
}
|
||||
|
||||
// FILE: j/J.java
|
||||
package j;
|
||||
|
||||
public interface J {
|
||||
public String get();
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_LIGHT_ANALYSIS
|
||||
// IGNORE_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// SAM_CONVERSIONS: INDY
|
||||
|
||||
// WITH_RUNTIME
|
||||
// FULL_JDK
|
||||
|
||||
// CHECK_BYTECODE_TEXT
|
||||
// 1 java/lang/invoke/LambdaMetafactory
|
||||
|
||||
// FILE: test.kt
|
||||
import c2.*
|
||||
|
||||
fun box(): String =
|
||||
C2().supplier().get()
|
||||
|
||||
// FILE: C1.kt
|
||||
package c1
|
||||
|
||||
open class C1 {
|
||||
protected fun test(): String = "OK"
|
||||
}
|
||||
|
||||
// FILE: C2.kt
|
||||
package c2
|
||||
|
||||
import c1.*
|
||||
import j.*
|
||||
|
||||
class C2 : C1() {
|
||||
fun supplier() = J(this::test)
|
||||
}
|
||||
|
||||
// FILE: j/J.java
|
||||
package j;
|
||||
|
||||
public interface J {
|
||||
public String get();
|
||||
}
|
||||
+9
-3
@@ -20936,9 +20936,15 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("protectedSuperclassCompanionObjectMember.kt")
|
||||
public void testProtectedSuperclassCompanionObjectMember() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/protectedSuperclassCompanionObjectMember.kt");
|
||||
@TestMetadata("protectedCompanionObjectStaticMember.kt")
|
||||
public void testProtectedCompanionObjectStaticMember() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/protectedCompanionObjectStaticMember.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("protectedMember.kt")
|
||||
public void testProtectedMember() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/protectedMember.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-3
@@ -20960,9 +20960,15 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("protectedSuperclassCompanionObjectMember.kt")
|
||||
public void testProtectedSuperclassCompanionObjectMember() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/protectedSuperclassCompanionObjectMember.kt");
|
||||
@TestMetadata("protectedCompanionObjectStaticMember.kt")
|
||||
public void testProtectedCompanionObjectStaticMember() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/protectedCompanionObjectStaticMember.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("protectedMember.kt")
|
||||
public void testProtectedMember() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/protectedMember.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-3
@@ -17482,9 +17482,14 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class WithAccessor extends AbstractLightAnalysisModeTest {
|
||||
@TestMetadata("protectedSuperclassCompanionObjectMember.kt")
|
||||
public void ignoreProtectedSuperclassCompanionObjectMember() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/protectedSuperclassCompanionObjectMember.kt");
|
||||
@TestMetadata("protectedCompanionObjectStaticMember.kt")
|
||||
public void ignoreProtectedCompanionObjectStaticMember() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/protectedCompanionObjectStaticMember.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("protectedMember.kt")
|
||||
public void ignoreProtectedMember() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/protectedMember.kt");
|
||||
}
|
||||
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user