JVM_IR: do not deep-copy suspend lambdas in initializers
This loses reflection metadata (and also sometimes fails). Which was missing anyway - this is also fixed now. #KT-42554 Fixed
This commit is contained in:
Generated
+5
@@ -27008,6 +27008,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
public void testReflectOnLambdaInSuspendLambda() throws Exception {
|
public void testReflectOnLambdaInSuspendLambda() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInSuspendLambda.kt");
|
runTest("compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInSuspendLambda.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("reflectOnSuspendLambdaInField.kt")
|
||||||
|
public void testReflectOnSuspendLambdaInField() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnSuspendLambdaInField.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/reflection/mapping")
|
@TestMetadata("compiler/testData/codegen/box/reflection/mapping")
|
||||||
|
|||||||
@@ -102,6 +102,12 @@ internal val propertiesPhase = makeIrFilePhase(
|
|||||||
stickyPostconditions = setOf((PropertiesLowering)::checkNoProperties)
|
stickyPostconditions = setOf((PropertiesLowering)::checkNoProperties)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
internal val IrClass.isGeneratedLambdaClass: Boolean
|
||||||
|
get() = origin == JvmLoweredDeclarationOrigin.LAMBDA_IMPL ||
|
||||||
|
origin == JvmLoweredDeclarationOrigin.SUSPEND_LAMBDA ||
|
||||||
|
origin == JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL ||
|
||||||
|
origin == JvmLoweredDeclarationOrigin.GENERATED_PROPERTY_REFERENCE
|
||||||
|
|
||||||
internal val localDeclarationsPhase = makeIrFilePhase(
|
internal val localDeclarationsPhase = makeIrFilePhase(
|
||||||
{ context ->
|
{ context ->
|
||||||
LocalDeclarationsLowering(
|
LocalDeclarationsLowering(
|
||||||
@@ -111,12 +117,10 @@ internal val localDeclarationsPhase = makeIrFilePhase(
|
|||||||
NameUtils.sanitizeAsJavaIdentifier(super.localName(declaration))
|
NameUtils.sanitizeAsJavaIdentifier(super.localName(declaration))
|
||||||
},
|
},
|
||||||
object : VisibilityPolicy {
|
object : VisibilityPolicy {
|
||||||
|
// Note: any condition that results in non-`LOCAL` visibility here should be duplicated in `JvmLocalClassPopupLowering`,
|
||||||
|
// else it won't detect the class as local.
|
||||||
override fun forClass(declaration: IrClass, inInlineFunctionScope: Boolean): DescriptorVisibility =
|
override fun forClass(declaration: IrClass, inInlineFunctionScope: Boolean): DescriptorVisibility =
|
||||||
if (declaration.origin == JvmLoweredDeclarationOrigin.LAMBDA_IMPL ||
|
if (declaration.isGeneratedLambdaClass) {
|
||||||
declaration.origin == JvmLoweredDeclarationOrigin.SUSPEND_LAMBDA ||
|
|
||||||
declaration.origin == JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL ||
|
|
||||||
declaration.origin == JvmLoweredDeclarationOrigin.GENERATED_PROPERTY_REFERENCE
|
|
||||||
) {
|
|
||||||
scopedVisibility(inInlineFunctionScope)
|
scopedVisibility(inInlineFunctionScope)
|
||||||
} else {
|
} else {
|
||||||
declaration.visibility
|
declaration.visibility
|
||||||
|
|||||||
+5
-8
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.common.lower.LocalClassPopupLowering
|
|||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.backend.jvm.ir.IrInlineReferenceLocator
|
import org.jetbrains.kotlin.backend.jvm.ir.IrInlineReferenceLocator
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.isGeneratedLambdaClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
||||||
|
|
||||||
@@ -31,15 +32,11 @@ class JvmLocalClassPopupLowering(context: JvmBackendContext) : LocalClassPopupLo
|
|||||||
// On JVM, we only pop up local classes in field initializers and anonymous init blocks, so that InitializersLowering would not copy
|
// On JVM, we only pop up local classes in field initializers and anonymous init blocks, so that InitializersLowering would not copy
|
||||||
// them to each constructor. (Moving all local classes is not possible because of cases where they use reified type parameters,
|
// them to each constructor. (Moving all local classes is not possible because of cases where they use reified type parameters,
|
||||||
// or capture crossinline lambdas.)
|
// or capture crossinline lambdas.)
|
||||||
// Upon moving such class, we record customEnclosingFunction for it to be the class constructor. This is needed because otherwise
|
// Upon moving such class, we record that it used to be in an initializer so that the codegen later sets its EnclosingMethod
|
||||||
// the class will not get any EnclosingMethod in the codegen later, since it won't be local anymore.
|
// to the primary constructor.
|
||||||
override fun shouldPopUp(klass: IrClass, currentScope: ScopeWithIr?): Boolean {
|
override fun shouldPopUp(klass: IrClass, currentScope: ScopeWithIr?): Boolean {
|
||||||
// On JVM, lambdas have package-private visibility after LocalDeclarationsLowering, so we have to check something else.
|
// On JVM, lambdas have package-private visibility after LocalDeclarationsLowering; see `forClass` in `localDeclarationsPhase`.
|
||||||
val isLocal = super.shouldPopUp(klass, currentScope) ||
|
if (!super.shouldPopUp(klass, currentScope) && !klass.isGeneratedLambdaClass) return false
|
||||||
klass.origin == JvmLoweredDeclarationOrigin.LAMBDA_IMPL ||
|
|
||||||
klass.origin == JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL ||
|
|
||||||
klass.origin == JvmLoweredDeclarationOrigin.GENERATED_PROPERTY_REFERENCE
|
|
||||||
if (!isLocal) return false
|
|
||||||
|
|
||||||
var parent = currentScope?.irElement
|
var parent = currentScope?.irElement
|
||||||
while (parent is IrFunction) {
|
while (parent is IrFunction) {
|
||||||
|
|||||||
+1
@@ -187,6 +187,7 @@ private class SuspendLambdaLowering(context: JvmBackendContext) : SuspendLowerin
|
|||||||
addInvokeCallingConstructor(constructor, invokeSuspend, invokeToOverride, parametersFields)
|
addInvokeCallingConstructor(constructor, invokeSuspend, invokeToOverride, parametersFields)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.metadata = function.metadata
|
||||||
context.suspendLambdaToOriginalFunctionMap[attributeOwnerId as IrFunctionReference] = function
|
context.suspendLambdaToOriginalFunctionMap[attributeOwnerId as IrFunctionReference] = function
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// WITH_REFLECT
|
||||||
|
|
||||||
|
import kotlin.reflect.jvm.reflect
|
||||||
|
|
||||||
|
class C {
|
||||||
|
val x: suspend (String) -> Unit = { OK: String -> }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return C().x.reflect()?.parameters?.singleOrNull()?.name ?: "null"
|
||||||
|
}
|
||||||
+5
@@ -28774,6 +28774,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
public void testReflectOnLambdaInSuspendLambda() throws Exception {
|
public void testReflectOnLambdaInSuspendLambda() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInSuspendLambda.kt");
|
runTest("compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInSuspendLambda.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("reflectOnSuspendLambdaInField.kt")
|
||||||
|
public void testReflectOnSuspendLambdaInField() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnSuspendLambdaInField.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/reflection/mapping")
|
@TestMetadata("compiler/testData/codegen/box/reflection/mapping")
|
||||||
|
|||||||
+5
@@ -26408,6 +26408,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
public void testReflectOnLambdaInSuspendLambda() throws Exception {
|
public void testReflectOnLambdaInSuspendLambda() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInSuspendLambda.kt");
|
runTest("compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInSuspendLambda.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("reflectOnSuspendLambdaInField.kt")
|
||||||
|
public void testReflectOnSuspendLambdaInField() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnSuspendLambdaInField.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/reflection/mapping")
|
@TestMetadata("compiler/testData/codegen/box/reflection/mapping")
|
||||||
|
|||||||
+5
@@ -27008,6 +27008,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
public void testReflectOnLambdaInSuspendLambda() throws Exception {
|
public void testReflectOnLambdaInSuspendLambda() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInSuspendLambda.kt");
|
runTest("compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInSuspendLambda.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("reflectOnSuspendLambdaInField.kt")
|
||||||
|
public void testReflectOnSuspendLambdaInField() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnSuspendLambdaInField.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/reflection/mapping")
|
@TestMetadata("compiler/testData/codegen/box/reflection/mapping")
|
||||||
|
|||||||
Reference in New Issue
Block a user