JVM_IR: Fix visibility of inner suspend lambda inside inline function

It should be public, otherwise, after inlining, we will get IllegalAccessError.
This commit is contained in:
Ilmir Usmanov
2020-01-09 15:48:19 +01:00
parent 56c8fdc6c4
commit 891a55d79a
2 changed files with 26 additions and 7 deletions
@@ -19,6 +19,8 @@ import org.jetbrains.kotlin.backend.jvm.localDeclarationsPhase
import org.jetbrains.kotlin.codegen.coroutines.* import org.jetbrains.kotlin.codegen.coroutines.*
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
@@ -69,7 +71,11 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
return context.createIrBuilder(expression.symbol, expression.startOffset, expression.endOffset).run { return context.createIrBuilder(expression.symbol, expression.startOffset, expression.endOffset).run {
val expressionArguments = expression.getArguments().map { it.second } val expressionArguments = expression.getArguments().map { it.second }
irBlock { irBlock {
+generateContinuationClassForLambda(info, currentDeclarationParent) +generateContinuationClassForLambda(
info,
currentDeclarationParent,
(currentFunction?.irElement as? IrFunction)?.isInline == true
)
val constructor = info.constructor val constructor = info.constructor
assert(constructor.valueParameters.size == expressionArguments.size + 1) { assert(constructor.valueParameters.size == expressionArguments.size + 1) {
"Inconsistency between callable reference to suspend lambda and the corresponding continuation" "Inconsistency between callable reference to suspend lambda and the corresponding continuation"
@@ -90,9 +96,19 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
}) })
} }
private fun generateContinuationClassForLambda(info: SuspendLambdaInfo, parent: IrDeclarationParent): IrClass { private fun generateContinuationClassForLambda(
info: SuspendLambdaInfo,
parent: IrDeclarationParent,
insideInlineFunction: Boolean
): IrClass {
val suspendLambda = context.ir.symbols.suspendLambdaClass.owner val suspendLambda = context.ir.symbols.suspendLambdaClass.owner
return suspendLambda.createContinuationClassFor(parent, JvmLoweredDeclarationOrigin.SUSPEND_LAMBDA).apply { return suspendLambda.createContinuationClassFor(
parent,
JvmLoweredDeclarationOrigin.SUSPEND_LAMBDA,
// Since inline functions can be inlined to different package, we should generate lambdas inside these functions
// as public
if (insideInlineFunction) Visibilities.PUBLIC else JavaVisibilities.PACKAGE_VISIBILITY
).apply {
copyAttributes(info.reference) copyAttributes(info.reference)
copyTypeParametersFrom(info.function) copyTypeParametersFrom(info.function)
val functionNClass = context.ir.symbols.getJvmFunctionClass(info.arity + 1) val functionNClass = context.ir.symbols.getJvmFunctionClass(info.arity + 1)
@@ -341,10 +357,14 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
} }
} }
private fun IrClass.createContinuationClassFor(parent: IrDeclarationParent, newOrigin: IrDeclarationOrigin): IrClass = buildClass { private fun IrClass.createContinuationClassFor(
parent: IrDeclarationParent,
newOrigin: IrDeclarationOrigin,
newVisibility: Visibility
): IrClass = buildClass {
name = Name.special("<Continuation>") name = Name.special("<Continuation>")
origin = newOrigin origin = newOrigin
visibility = JavaVisibilities.PACKAGE_VISIBILITY visibility = newVisibility
}.also { irClass -> }.also { irClass ->
irClass.createImplicitParameterDeclarationWithWrappedDescriptor() irClass.createImplicitParameterDeclarationWithWrappedDescriptor()
irClass.superTypes.add(defaultType) irClass.superTypes.add(defaultType)
@@ -394,7 +414,7 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
attributeContainer: IrAttributeContainer attributeContainer: IrAttributeContainer
): IrClass { ): IrClass {
return context.ir.symbols.continuationImplClass.owner return context.ir.symbols.continuationImplClass.owner
.createContinuationClassFor(irFunction, JvmLoweredDeclarationOrigin.CONTINUATION_CLASS) .createContinuationClassFor(irFunction, JvmLoweredDeclarationOrigin.CONTINUATION_CLASS, JavaVisibilities.PACKAGE_VISIBILITY)
.apply { .apply {
copyTypeParametersFrom(irFunction) copyTypeParametersFrom(irFunction)
val resultField = addField( val resultField = addField(
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// FILE: flow.kt // FILE: flow.kt
// COMMON_COROUTINES_TEST // COMMON_COROUTINES_TEST