JVM_IR KT-48954 prohibit indy reference creation in some cases
This commit is contained in:
committed by
TeamCityServer
parent
7552767d85
commit
1dae2aca4c
+6
@@ -42192,6 +42192,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/syntheticAccessors/kt48331.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt48954.kt")
|
||||
public void testKt48954() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/syntheticAccessors/kt48954.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt9717.kt")
|
||||
public void testKt9717() throws Exception {
|
||||
|
||||
+15
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.common.lower.VariableRemapper
|
||||
import org.jetbrains.kotlin.backend.common.lower.parents
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.findSuperDeclaration
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.getSingleAbstractMethod
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.isCompiledToJvmDefault
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.findInterfaceImplementation
|
||||
@@ -26,6 +27,7 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -78,6 +80,7 @@ internal class LambdaMetafactoryArgumentsBuilder(
|
||||
// TODO in cases where LambdaMetafactory is unusable directly due to problems with the implementation function,
|
||||
// we can still avoid generating an entire class by converting the function reference into a lambda first;
|
||||
// see `InlineCallableReferenceToLambdaPhase`
|
||||
|
||||
val implFun = reference.symbol.owner
|
||||
|
||||
// Don't generate references to intrinsic functions as invokedynamic (no such method exists at run-time).
|
||||
@@ -97,6 +100,18 @@ internal class LambdaMetafactoryArgumentsBuilder(
|
||||
return null
|
||||
}
|
||||
|
||||
// It's possible to reference through a child class a method declared in a package-private base Java class.
|
||||
// In this case the corresponding method might be inaccessible in the context where it's referenced (see KT-48954).
|
||||
// For now, just prohibit referencing methods from package-private Java classes through indy (without precise accessibility check).
|
||||
// TODO wrap into lambda?
|
||||
if (implFun is IrSimpleFunction) {
|
||||
val baseFun = findSuperDeclaration(implFun, false, context.state.jvmDefaultMode)
|
||||
val baseFunClass = baseFun.parent as? IrClass
|
||||
if (baseFunClass != null && baseFunClass.visibility == JavaDescriptorVisibilities.PACKAGE_VISIBILITY) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
val implFunParent = implFun.parent
|
||||
if (implFunParent is IrClass && implFunParent.origin == IrDeclarationOrigin.JVM_MULTIFILE_CLASS) {
|
||||
// LambdaMetafactory treats multifile class part members as non-accessible,
|
||||
|
||||
+2
-23
@@ -428,29 +428,8 @@ class MethodSignatureMapper(private val context: JvmBackendContext) {
|
||||
fun mapCalleeToAsmMethod(function: IrSimpleFunction, isSuperCall: Boolean = false): Method =
|
||||
mapAsmMethod(findSuperDeclaration(function, isSuperCall))
|
||||
|
||||
// Copied from KotlinTypeMapper.findSuperDeclaration.
|
||||
internal fun findSuperDeclaration(function: IrSimpleFunction, isSuperCall: Boolean): IrSimpleFunction {
|
||||
var current = function
|
||||
while (current.isFakeOverride) {
|
||||
// TODO: probably isJvmInterface instead of isInterface, here and in KotlinTypeMapper
|
||||
val classCallable = current.overriddenSymbols.firstOrNull { !it.owner.parentAsClass.isInterface }?.owner
|
||||
if (classCallable != null) {
|
||||
current = classCallable
|
||||
continue
|
||||
}
|
||||
if (isSuperCall && !current.parentAsClass.isInterface &&
|
||||
current.resolveFakeOverride()?.run {
|
||||
isMethodOfAny() || !isCompiledToJvmDefault(context.state.jvmDefaultMode)
|
||||
} == true
|
||||
) {
|
||||
return current
|
||||
}
|
||||
|
||||
current = current.overriddenSymbols.firstOrNull()?.owner
|
||||
?: error("Fake override should have at least one overridden descriptor: ${current.render()}")
|
||||
}
|
||||
return current
|
||||
}
|
||||
private fun findSuperDeclaration(function: IrSimpleFunction, isSuperCall: Boolean): IrSimpleFunction =
|
||||
findSuperDeclaration(function, isSuperCall, context.state.jvmDefaultMode)
|
||||
|
||||
private fun getJvmMethodNameIfSpecial(irFunction: IrSimpleFunction): String? {
|
||||
if (irFunction.origin == JvmLoweredDeclarationOrigin.STATIC_INLINE_CLASS_REPLACEMENT) {
|
||||
|
||||
+2
-1
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.*
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.findSuperDeclaration
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||
@@ -106,7 +107,7 @@ object JvmInvokeDynamic : IntrinsicMethod() {
|
||||
is IrSimpleFunction -> {
|
||||
// Note that if the given function is a fake override, we emit a method handle with explicit super class.
|
||||
// This has the same binary compatibility guarantees as in Java.
|
||||
codegen.methodSignatureMapper.findSuperDeclaration(irFun0, false)
|
||||
findSuperDeclaration(irFun0, false, codegen.state.jvmDefaultMode)
|
||||
}
|
||||
else ->
|
||||
throw java.lang.AssertionError("Simple function or constructor expected: ${irFun0.render()}")
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.backend.jvm.ir
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ir.ir2string
|
||||
import org.jetbrains.kotlin.backend.common.ir.isMethodOfAny
|
||||
import org.jetbrains.kotlin.backend.common.lower.at
|
||||
import org.jetbrains.kotlin.backend.common.lower.irNot
|
||||
import org.jetbrains.kotlin.backend.jvm.CachedFieldsForObjectInstances
|
||||
@@ -395,3 +396,26 @@ fun IrDeclarationParent.getCallableReferenceOwnerKClassType(context: JvmBackendC
|
||||
|
||||
fun IrDeclaration.getCallableReferenceTopLevelFlag(): Int =
|
||||
if (parent.let { it is IrClass && it.isFileClass }) 1 else 0
|
||||
|
||||
// Based on KotlinTypeMapper.findSuperDeclaration.
|
||||
fun findSuperDeclaration(function: IrSimpleFunction, isSuperCall: Boolean, jvmDefaultMode: JvmDefaultMode): IrSimpleFunction {
|
||||
var current = function
|
||||
while (current.isFakeOverride) {
|
||||
// TODO: probably isJvmInterface instead of isInterface, here and in KotlinTypeMapper
|
||||
val classCallable = current.overriddenSymbols.firstOrNull { !it.owner.parentAsClass.isInterface }?.owner
|
||||
if (classCallable != null) {
|
||||
current = classCallable
|
||||
continue
|
||||
}
|
||||
if (isSuperCall && !current.parentAsClass.isInterface) {
|
||||
val overridden = current.resolveFakeOverride()
|
||||
if (overridden != null && (overridden.isMethodOfAny() || !overridden.isCompiledToJvmDefault(jvmDefaultMode))) {
|
||||
return current
|
||||
}
|
||||
}
|
||||
|
||||
current = current.overriddenSymbols.firstOrNull()?.owner
|
||||
?: error("Fake override should have at least one overridden descriptor: ${current.render()}")
|
||||
}
|
||||
return current
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// FULL_JDK
|
||||
// JVM_TARGET: 1.8
|
||||
|
||||
// FILE: kt48954.kt
|
||||
import lib.*
|
||||
import app.*
|
||||
|
||||
fun box(): String {
|
||||
val foo = Foo()
|
||||
Service(foo::bar).test()
|
||||
return foo.p
|
||||
}
|
||||
|
||||
// FILE: app/Service.kt
|
||||
package app
|
||||
|
||||
import java.util.function.Consumer
|
||||
|
||||
class Service(private val consumer: Consumer<String>) {
|
||||
fun test() {
|
||||
consumer.accept("OK")
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: lib/PackagePrivateBase.java
|
||||
package lib;
|
||||
|
||||
class PackagePrivateBase {
|
||||
public String p;
|
||||
|
||||
public void bar(String param) {
|
||||
this.p = param;
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: lib/Foo.java
|
||||
package lib;
|
||||
|
||||
public class Foo extends PackagePrivateBase {
|
||||
}
|
||||
+6
@@ -42036,6 +42036,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/syntheticAccessors/kt48331.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt48954.kt")
|
||||
public void testKt48954() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/syntheticAccessors/kt48954.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt9717.kt")
|
||||
public void testKt9717() throws Exception {
|
||||
|
||||
+6
@@ -42192,6 +42192,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/syntheticAccessors/kt48331.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt48954.kt")
|
||||
public void testKt48954() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/syntheticAccessors/kt48954.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt9717.kt")
|
||||
public void testKt9717() throws Exception {
|
||||
|
||||
+5
@@ -33839,6 +33839,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/syntheticAccessors/kt48331.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt48954.kt")
|
||||
public void testKt48954() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/syntheticAccessors/kt48954.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt9717.kt")
|
||||
public void testKt9717() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/syntheticAccessors/kt9717.kt");
|
||||
|
||||
Reference in New Issue
Block a user