diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt index ce0b84317ee..e1f143c3216 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt @@ -49,7 +49,8 @@ open class DefaultArgumentStubGenerator( } private fun lower(irFunction: IrFunction): List { - val newIrFunction = irFunction.generateDefaultsFunction(context, skipInlineMethods, skipExternalMethods) + val visibility = defaultArgumentStubVisibility(irFunction) + val newIrFunction = irFunction.generateDefaultsFunction(context, skipInlineMethods, skipExternalMethods, visibility) ?: return listOf(irFunction) if (newIrFunction.origin == IrDeclarationOrigin.FAKE_OVERRIDE) { return listOf(irFunction, newIrFunction) @@ -185,6 +186,8 @@ open class DefaultArgumentStubGenerator( error("This method should be overridden") } + protected open fun defaultArgumentStubVisibility(function: IrFunction) = Visibilities.PUBLIC + private fun log(msg: () -> String) = context.log { "DEFAULT-REPLACER: ${msg()}" } } @@ -271,8 +274,8 @@ open class DefaultParameterInjector( val startOffset = expression.startOffset val endOffset = expression.endOffset val declaration = expression.symbol.owner - - val stubOverride = declaration.generateDefaultsFunction(context, skipInline, skipExternalMethods) ?: return null + val visibility = defaultArgumentStubVisibility(declaration) + val stubOverride = declaration.generateDefaultsFunction(context, skipInline, skipExternalMethods, visibility) ?: return null // We *have* to resolve the fake override here since on the JVM, a default stub for a function implemented // in an interface does not leave an abstract method after being moved to DefaultImpls (see InterfaceLowering). // Calling the fake override on an implementation of that interface would then result in a call to a method @@ -319,6 +322,8 @@ open class DefaultParameterInjector( protected open fun nullConst(startOffset: Int, endOffset: Int, type: IrType): IrExpression = IrConstImpl.defaultValueForType(startOffset, endOffset, type) + protected open fun defaultArgumentStubVisibility(function: IrFunction) = Visibilities.PUBLIC + private fun log(msg: () -> String) = context.log { "DEFAULT-INJECTOR: ${msg()}" } } @@ -333,7 +338,8 @@ class DefaultParameterCleaner constructor(val context: CommonBackendContext) : F private fun IrFunction.generateDefaultsFunction( context: CommonBackendContext, skipInlineMethods: Boolean, - skipExternalMethods: Boolean + skipExternalMethods: Boolean, + visibility: Visibility ): IrFunction? { if (skipInlineMethods && isInline) return null if (skipExternalMethods && isExternalOrInheritedFromExternal()) return null @@ -341,10 +347,15 @@ private fun IrFunction.generateDefaultsFunction( if (this is IrSimpleFunction) { // If this is an override of a function with default arguments, produce a fake override of a default stub. val overriddenStubs = overriddenSymbols.mapNotNull { - it.owner.generateDefaultsFunction(context, skipInlineMethods, skipExternalMethods)?.symbol as IrSimpleFunctionSymbol? + it.owner.generateDefaultsFunction( + context, + skipInlineMethods, + skipExternalMethods, + visibility + )?.symbol as IrSimpleFunctionSymbol? } if (overriddenStubs.isNotEmpty()) { - return generateDefaultsFunctionImpl(context, IrDeclarationOrigin.FAKE_OVERRIDE).also { + return generateDefaultsFunctionImpl(context, IrDeclarationOrigin.FAKE_OVERRIDE, visibility).also { (it as IrSimpleFunction).overriddenSymbols.addAll(overriddenStubs) context.ir.defaultParameterDeclarationsCache[this] = it } @@ -361,14 +372,18 @@ private fun IrFunction.generateDefaultsFunction( // Since this bug causes the metadata serializer to write the "has default value" flag into compiled // binaries, it's way too late to fix it. Hence the workaround. if (valueParameters.any { it.defaultValue != null }) { - return generateDefaultsFunctionImpl(context, IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER).also { + return generateDefaultsFunctionImpl(context, IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER, visibility).also { context.ir.defaultParameterDeclarationsCache[this] = it } } return null } -private fun IrFunction.generateDefaultsFunctionImpl(context: CommonBackendContext, newOrigin: IrDeclarationOrigin): IrFunction { +private fun IrFunction.generateDefaultsFunctionImpl( + context: CommonBackendContext, + newOrigin: IrDeclarationOrigin, + newVisibility: Visibility +): IrFunction { val newFunction = when (this) { is IrConstructor -> buildConstructor { @@ -377,7 +392,7 @@ private fun IrFunction.generateDefaultsFunctionImpl(context: CommonBackendContex isExternal = false isPrimary = false isExpect = false - visibility = Visibilities.PUBLIC + visibility = newVisibility } is IrSimpleFunction -> buildFunWithDescriptorForInlining(descriptor) { @@ -387,7 +402,7 @@ private fun IrFunction.generateDefaultsFunctionImpl(context: CommonBackendContex modality = Modality.FINAL isExternal = false isTailrec = false - visibility = Visibilities.PUBLIC + visibility = newVisibility } else -> throw IllegalStateException("Unknown function type") } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt index 21a597030ad..67b8b234e4e 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.backend.jvm.codegen +import org.jetbrains.kotlin.backend.common.ir.ir2string import org.jetbrains.kotlin.backend.common.lower.BOUND_RECEIVER_PARAMETER import org.jetbrains.kotlin.backend.common.lower.BOUND_VALUE_PARAMETER import org.jetbrains.kotlin.backend.jvm.JvmBackendContext @@ -16,9 +17,11 @@ import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.visitAnnotableParameterCount import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.load.java.JavaVisibilities import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtElement @@ -134,9 +137,16 @@ open class FunctionCodegen( private fun continuationClass(): IrClass = irFunction.body!!.statements[0] as IrClass + private fun IrFunction.getVisibilityForDefaultArgumentStub(): Int = + when (visibility) { + Visibilities.PUBLIC -> Opcodes.ACC_PUBLIC + JavaVisibilities.PACKAGE_VISIBILITY -> AsmUtil.NO_FLAG_PACKAGE_PRIVATE + else -> throw IllegalStateException("Default argument stub should be either public or package private: ${ir2string(this)}") + } + private fun calculateMethodFlags(isStatic: Boolean): Int { if (irFunction.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER) { - return Opcodes.ACC_PUBLIC or Opcodes.ACC_SYNTHETIC.let { + return irFunction.getVisibilityForDefaultArgumentStub() or Opcodes.ACC_SYNTHETIC.let { if (irFunction is IrConstructor) it else it or Opcodes.ACC_STATIC } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt index 7f0b4639120..cddf68856ff 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt @@ -165,7 +165,6 @@ fun IrDeclarationWithVisibility.getVisibilityAccessFlag(kind: OwnerKind? = null) ?: visibilityToAccessFlag[visibility] ?: throw IllegalStateException("$visibility is not a valid visibility in backend for ${ir2string(this)}") - private fun IrDeclarationWithVisibility.specialCaseVisibility(kind: OwnerKind?): Int? { // if (JvmCodegenUtil.isNonIntrinsicPrivateCompanionObjectInInterface(memberDescriptor)) { // return ACC_PUBLIC @@ -284,12 +283,11 @@ fun IrDeclarationWithVisibility.isEffectivelyInlineOnly(): Boolean = (this is IrSimpleFunction && isSuspend && isInline && (valueParameters.any { it.isCrossinline } || visibility === Visibilities.PRIVATE)) -private fun IrFunction.isInlineOnly() = +fun IrFunction.isInlineOnly() = isInline && hasAnnotation(INLINE_ONLY_ANNOTATION_FQ_NAME) private fun IrFunction.isReifiable() = typeParameters.any { it.isReified } - // Borrowed with modifications from ImplementationBodyCodegen.java private val KOTLIN_MARKER_INTERFACES: Map = run { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt index 6104c126cd1..06ecaf0fff0 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.jvm.ir import org.jetbrains.kotlin.backend.common.lower.IrLoweringContext import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmSymbols +import org.jetbrains.kotlin.backend.jvm.codegen.isInlineOnly import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface import org.jetbrains.kotlin.backend.jvm.descriptors.JvmDeclarationFactory import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.hasMangledParameters @@ -28,6 +29,7 @@ import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.load.java.JavaVisibilities import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_DEFAULT_FQ_NAME @@ -99,6 +101,9 @@ val IrFunction.propertyIfAccessor: IrDeclaration fun IrFunction.hasJvmDefault(): Boolean = propertyIfAccessor.hasAnnotation(JVM_DEFAULT_FQ_NAME) +fun IrFunction.getJvmVisibilityOfDefaultArgumentStub() = + if (Visibilities.isPrivate(visibility) || isInlineOnly()) JavaVisibilities.PACKAGE_VISIBILITY else Visibilities.PUBLIC + fun IrValueParameter.isInlineParameter(type: IrType = this.type) = index >= 0 && !isNoinline && !type.isNullable() && (type.isFunction() || type.isSuspendFunctionTypeOrSubtype()) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/EnumClassLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/EnumClassLowering.kt index 11873fea225..582cbb4537e 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/EnumClassLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/EnumClassLowering.kt @@ -138,7 +138,7 @@ private class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringP enumConstructor.origin, IrConstructorSymbolImpl(descriptor), enumConstructor.name, - Visibilities.PRIVATE, + enumConstructor.visibility, returnType = enumConstructor.returnType, isInline = enumConstructor.isInline, isExternal = enumConstructor.isExternal, diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultArgumentStubGenerator.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultArgumentStubGenerator.kt index da34e14c414..9ad9c051b90 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultArgumentStubGenerator.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultArgumentStubGenerator.kt @@ -8,9 +8,11 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.common.lower.DefaultArgumentStubGenerator import org.jetbrains.kotlin.backend.common.lower.irIfThen import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.backend.jvm.ir.getJvmVisibilityOfDefaultArgumentStub import org.jetbrains.kotlin.ir.builders.IrBlockBodyBuilder import org.jetbrains.kotlin.ir.builders.irCall import org.jetbrains.kotlin.ir.builders.irGet +import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrValueDeclaration import org.jetbrains.kotlin.ir.declarations.IrValueParameter import org.jetbrains.kotlin.ir.expressions.IrExpression @@ -43,4 +45,6 @@ class JvmDefaultArgumentStubGenerator(override val context: JvmBackendContext) : }) return parameter } + + override fun defaultArgumentStubVisibility(function: IrFunction) = function.getJvmVisibilityOfDefaultArgumentStub() } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultParameterInjector.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultParameterInjector.kt index feb202e1597..62f21f8cd11 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultParameterInjector.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultParameterInjector.kt @@ -7,7 +7,9 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.common.lower.DefaultParameterInjector import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.backend.jvm.ir.getJvmVisibilityOfDefaultArgumentStub import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.unboxInlineClass +import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrValueParameter import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl @@ -34,4 +36,6 @@ class JvmDefaultParameterInjector(context: JvmBackendContext) : putValueArgument(0, super.nullConst(startOffset, endOffset, underlyingType)) } } + + override fun defaultArgumentStubVisibility(function: IrFunction) = function.getJvmVisibilityOfDefaultArgumentStub() } diff --git a/compiler/testData/codegen/box/reflection/callBy/privateMemberFunction.kt b/compiler/testData/codegen/box/reflection/callBy/privateMemberFunction.kt index b83c9316a1c..ff7ee83ea00 100644 --- a/compiler/testData/codegen/box/reflection/callBy/privateMemberFunction.kt +++ b/compiler/testData/codegen/box/reflection/callBy/privateMemberFunction.kt @@ -1,5 +1,4 @@ // IGNORE_BACKEND_FIR: JVM_IR -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // WITH_REFLECT diff --git a/compiler/testData/writeFlags/function/withDefaultArguments/funInClass.kt b/compiler/testData/writeFlags/function/withDefaultArguments/funInClass.kt index 3c3b6ad3cd6..dcd7416e707 100644 --- a/compiler/testData/writeFlags/function/withDefaultArguments/funInClass.kt +++ b/compiler/testData/writeFlags/function/withDefaultArguments/funInClass.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR open class MyClass() { fun testPublic(s: String = "") {} diff --git a/compiler/testData/writeFlags/function/withDefaultArguments/inlineOnlyFunInClass.kt b/compiler/testData/writeFlags/function/withDefaultArguments/inlineOnlyFunInClass.kt index fbca2ef0456..5a7d777311f 100644 --- a/compiler/testData/writeFlags/function/withDefaultArguments/inlineOnlyFunInClass.kt +++ b/compiler/testData/writeFlags/function/withDefaultArguments/inlineOnlyFunInClass.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR class MyClass() { @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") @kotlin.internal.InlineOnly