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
|
@Test
|
||||||
@TestMetadata("protectedSuperclassCompanionObjectMember.kt")
|
@TestMetadata("protectedCompanionObjectStaticMember.kt")
|
||||||
public void testProtectedSuperclassCompanionObjectMember() throws Exception {
|
public void testProtectedCompanionObjectStaticMember() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/protectedSuperclassCompanionObjectMember.kt");
|
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()}")
|
?: throw AssertionError("'implMethodReference' is expected to be 'IrFunctionReference': ${call.dump()}")
|
||||||
val implFunSymbol = implFunRef.symbol
|
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 accessorSymbol = createAccessor(implFunSymbol, implFunRef.dispatchReceiver?.type, null)
|
||||||
val accessorFun = accessorSymbol.owner
|
val accessorFun = accessorSymbol.owner
|
||||||
@@ -212,6 +213,23 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
|
|||||||
return call
|
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 {
|
override fun visitGetField(expression: IrGetField): IrExpression {
|
||||||
val dispatchReceiverType = expression.receiver?.type
|
val dispatchReceiverType = expression.receiver?.type
|
||||||
return super.visitExpression(
|
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.
|
// If local variables are accessible by Kotlin rules, they also are by Java rules.
|
||||||
val ownerClass = declaration.parent as? IrClass ?: return true
|
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 context = currentScope!!.irElement as IrDeclaration
|
||||||
var throughCrossinlineLambda = false
|
var throughCrossinlineLambda = false
|
||||||
while (context !is IrClass) {
|
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
|
// 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.
|
// calling methods on `super` we also need an accessor to satisfy INVOKESPECIAL constraints.
|
||||||
// TODO scan nested classes for calls to private inline functions?
|
// TODO scan nested classes for calls to private inline functions?
|
||||||
return false
|
return null
|
||||||
} else {
|
} else {
|
||||||
context = context.parent as? IrDeclaration ?: return false
|
context = context.parent as? IrDeclaration
|
||||||
|
?: return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return OuterClassInfo(context, throughCrossinlineLambda)
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// monitorEnter/monitorExit are the only functions which are accessed "illegally" (see kotlin/util/Synchronized.kt).
|
// monitorEnter/monitorExit are the only functions which are accessed "illegally" (see kotlin/util/Synchronized.kt).
|
||||||
|
|||||||
+10
-2
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
// CHECK_BYTECODE_TEXT
|
// CHECK_BYTECODE_TEXT
|
||||||
// 1 java/lang/invoke/LambdaMetafactory
|
// 1 java/lang/invoke/LambdaMetafactory
|
||||||
|
// 1 c2/C2\.access\$test\$s[0-9]+\(\)Ljava/lang/String\;
|
||||||
|
|
||||||
// FILE: test.kt
|
// FILE: test.kt
|
||||||
import c2.*
|
import c2.*
|
||||||
@@ -29,8 +30,15 @@ open class C1 {
|
|||||||
package c2
|
package c2
|
||||||
|
|
||||||
import c1.*
|
import c1.*
|
||||||
import java.util.function.Supplier
|
import j.*
|
||||||
|
|
||||||
class C2 : C1() {
|
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
|
@Test
|
||||||
@TestMetadata("protectedSuperclassCompanionObjectMember.kt")
|
@TestMetadata("protectedCompanionObjectStaticMember.kt")
|
||||||
public void testProtectedSuperclassCompanionObjectMember() throws Exception {
|
public void testProtectedCompanionObjectStaticMember() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/protectedSuperclassCompanionObjectMember.kt");
|
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
|
@Test
|
||||||
@TestMetadata("protectedSuperclassCompanionObjectMember.kt")
|
@TestMetadata("protectedCompanionObjectStaticMember.kt")
|
||||||
public void testProtectedSuperclassCompanionObjectMember() throws Exception {
|
public void testProtectedCompanionObjectStaticMember() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/protectedSuperclassCompanionObjectMember.kt");
|
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")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
public static class WithAccessor extends AbstractLightAnalysisModeTest {
|
public static class WithAccessor extends AbstractLightAnalysisModeTest {
|
||||||
@TestMetadata("protectedSuperclassCompanionObjectMember.kt")
|
@TestMetadata("protectedCompanionObjectStaticMember.kt")
|
||||||
public void ignoreProtectedSuperclassCompanionObjectMember() throws Exception {
|
public void ignoreProtectedCompanionObjectStaticMember() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/protectedSuperclassCompanionObjectMember.kt");
|
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 {
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user