From 66bbd3e10200ae7f8d8736cc81b0c2ce9366f3ca Mon Sep 17 00:00:00 2001 From: Igor Chevdar Date: Thu, 4 Jun 2020 18:44:46 +0500 Subject: [PATCH] [IR] Improved tuning of SAM wrapper visibility --- .../common/lower/SingleAbstractMethodLowering.kt | 14 +++++++------- .../js/lower/JsSingleAbstractMethodLowering.kt | 8 ++++++++ .../jvm/lower/JvmSingleAbstractMethodLowering.kt | 8 ++++++-- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/SingleAbstractMethodLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/SingleAbstractMethodLowering.kt index 79d4a2c5d98..09cd40da14f 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/SingleAbstractMethodLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/SingleAbstractMethodLowering.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.common.lower import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext +import org.jetbrains.kotlin.backend.common.ScopeWithIr import org.jetbrains.kotlin.backend.common.ir.addFakeOverridesViaIncorrectHeuristic import org.jetbrains.kotlin.backend.common.ir.copyTo import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor @@ -61,11 +62,12 @@ abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) : private val inlineCachedImplementations = mutableMapOf() private var enclosingContainer: IrDeclarationContainer? = null - open val privateGeneratedWrapperVisibility: Visibility - get() = Visibilities.PRIVATE + abstract fun getWrapperVisibility(expression: IrTypeOperatorCall, scopes: List): Visibility abstract fun getSuperTypeForWrapper(typeOperand: IrType): IrType + open val inInlineFunctionScope get() = allScopes.any { scope -> (scope.irElement as? IrFunction)?.isInline ?: false } + override fun lower(irFile: IrFile) { cachedImplementations.clear() inlineCachedImplementations.clear() @@ -102,10 +104,9 @@ abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) : if (invokable.isNullConst()) return invokable - val inInlineFunctionScope = allScopes.any { scope -> (scope.irElement as? IrFunction)?.isInline ?: false } val cache = if (inInlineFunctionScope) inlineCachedImplementations else cachedImplementations val implementation = cache.getOrPut(erasedSuperType) { - createObjectProxy(erasedSuperType, inInlineFunctionScope, expression) + createObjectProxy(erasedSuperType, getWrapperVisibility(expression, allScopes), expression) } return if (superType.isNullable() && invokable.type.isNullable()) { @@ -136,14 +137,14 @@ abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) : // Construct a class that wraps an invokable object into an implementation of an interface: // class sam$n(private val invokable: F) : Interface { override fun method(...) = invokable(...) } - private fun createObjectProxy(superType: IrType, generatePublicWrapper: Boolean, createFor: IrElement): IrClass { + private fun createObjectProxy(superType: IrType, wrapperVisibility: Visibility, createFor: IrElement): IrClass { val superClass = superType.classifierOrFail.owner as IrClass // The language documentation prohibits casting lambdas to classes, but if it was allowed, // the `irDelegatingConstructorCall` in the constructor below would need to be modified. assert(superClass.kind == ClassKind.INTERFACE) { "SAM conversion to an abstract class not allowed" } val superFqName = superClass.fqNameWhenAvailable!!.asString().replace('.', '_') - val inlinePrefix = if (generatePublicWrapper) "\$i" else "" + val inlinePrefix = if (wrapperVisibility == Visibilities.PUBLIC) "\$i" else "" val wrapperName = Name.identifier("sam$inlinePrefix\$$superFqName$SAM_WRAPPER_SUFFIX") val superMethod = superClass.functions.single { it.modality == Modality.ABSTRACT } // TODO: have psi2ir cast the argument to the correct function type. Also see the TODO @@ -155,7 +156,6 @@ abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) : context.ir.symbols.functionN(superMethod.valueParameters.size).owner val wrappedFunctionType = wrappedFunctionClass.defaultType - val wrapperVisibility = if (generatePublicWrapper) Visibilities.PUBLIC else privateGeneratedWrapperVisibility val subclass = buildClass { name = wrapperName origin = IrDeclarationOrigin.GENERATED_SAM_IMPLEMENTATION diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsSingleAbstractMethodLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsSingleAbstractMethodLowering.kt index 1e36163dbd0..2a1b3d6d148 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsSingleAbstractMethodLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsSingleAbstractMethodLowering.kt @@ -5,14 +5,22 @@ package org.jetbrains.kotlin.ir.backend.js.lower +import org.jetbrains.kotlin.backend.common.ScopeWithIr import org.jetbrains.kotlin.backend.common.lower.SingleAbstractMethodLowering +import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext +import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.classOrNull import org.jetbrains.kotlin.ir.types.defaultType import org.jetbrains.kotlin.ir.util.render class JsSingleAbstractMethodLowering(context: JsIrBackendContext) : SingleAbstractMethodLowering(context) { + override fun getWrapperVisibility(expression: IrTypeOperatorCall, scopes: List): Visibility { + return Visibilities.PRIVATE + } + override fun getSuperTypeForWrapper(typeOperand: IrType): IrType { // FE doesn't allow type parameters for now. // And since there is a to-do in common SingleAbstractMethodLowering (at function visitTypeOperator), diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmSingleAbstractMethodLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmSingleAbstractMethodLowering.kt index cd3789c49ad..b503e21481c 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmSingleAbstractMethodLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmSingleAbstractMethodLowering.kt @@ -5,11 +5,13 @@ package org.jetbrains.kotlin.backend.jvm.lower +import org.jetbrains.kotlin.backend.common.ScopeWithIr import org.jetbrains.kotlin.backend.common.lower.SingleAbstractMethodLowering import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound +import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.declarations.addFunction @@ -17,8 +19,10 @@ import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin import org.jetbrains.kotlin.ir.declarations.IrField +import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.getClass import org.jetbrains.kotlin.ir.types.typeWith @@ -35,8 +39,8 @@ internal val singleAbstractMethodPhase = makeIrFilePhase( private class JvmSingleAbstractMethodLowering(context: JvmBackendContext) : SingleAbstractMethodLowering(context) { private val jvmContext: JvmBackendContext get() = context as JvmBackendContext - override val privateGeneratedWrapperVisibility: Visibility - get() = JavaVisibilities.PACKAGE_VISIBILITY + override fun getWrapperVisibility(expression: IrTypeOperatorCall, scopes: List) = + if (inInlineFunctionScope) Visibilities.PUBLIC else JavaVisibilities.PACKAGE_VISIBILITY override fun getSuperTypeForWrapper(typeOperand: IrType): IrType = typeOperand.erasedUpperBound.defaultType