[IR] Improved tuning of SAM wrapper visibility
This commit is contained in:
+7
-7
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.common.lower
|
|||||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
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.addFakeOverridesViaIncorrectHeuristic
|
||||||
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
||||||
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
|
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
|
||||||
@@ -61,11 +62,12 @@ abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) :
|
|||||||
private val inlineCachedImplementations = mutableMapOf<IrType, IrClass>()
|
private val inlineCachedImplementations = mutableMapOf<IrType, IrClass>()
|
||||||
private var enclosingContainer: IrDeclarationContainer? = null
|
private var enclosingContainer: IrDeclarationContainer? = null
|
||||||
|
|
||||||
open val privateGeneratedWrapperVisibility: Visibility
|
abstract fun getWrapperVisibility(expression: IrTypeOperatorCall, scopes: List<ScopeWithIr>): Visibility
|
||||||
get() = Visibilities.PRIVATE
|
|
||||||
|
|
||||||
abstract fun getSuperTypeForWrapper(typeOperand: IrType): IrType
|
abstract fun getSuperTypeForWrapper(typeOperand: IrType): IrType
|
||||||
|
|
||||||
|
open val inInlineFunctionScope get() = allScopes.any { scope -> (scope.irElement as? IrFunction)?.isInline ?: false }
|
||||||
|
|
||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
cachedImplementations.clear()
|
cachedImplementations.clear()
|
||||||
inlineCachedImplementations.clear()
|
inlineCachedImplementations.clear()
|
||||||
@@ -102,10 +104,9 @@ abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) :
|
|||||||
if (invokable.isNullConst())
|
if (invokable.isNullConst())
|
||||||
return invokable
|
return invokable
|
||||||
|
|
||||||
val inInlineFunctionScope = allScopes.any { scope -> (scope.irElement as? IrFunction)?.isInline ?: false }
|
|
||||||
val cache = if (inInlineFunctionScope) inlineCachedImplementations else cachedImplementations
|
val cache = if (inInlineFunctionScope) inlineCachedImplementations else cachedImplementations
|
||||||
val implementation = cache.getOrPut(erasedSuperType) {
|
val implementation = cache.getOrPut(erasedSuperType) {
|
||||||
createObjectProxy(erasedSuperType, inInlineFunctionScope, expression)
|
createObjectProxy(erasedSuperType, getWrapperVisibility(expression, allScopes), expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
return if (superType.isNullable() && invokable.type.isNullable()) {
|
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:
|
// 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(...) }
|
// 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
|
val superClass = superType.classifierOrFail.owner as IrClass
|
||||||
// The language documentation prohibits casting lambdas to classes, but if it was allowed,
|
// The language documentation prohibits casting lambdas to classes, but if it was allowed,
|
||||||
// the `irDelegatingConstructorCall` in the constructor below would need to be modified.
|
// the `irDelegatingConstructorCall` in the constructor below would need to be modified.
|
||||||
assert(superClass.kind == ClassKind.INTERFACE) { "SAM conversion to an abstract class not allowed" }
|
assert(superClass.kind == ClassKind.INTERFACE) { "SAM conversion to an abstract class not allowed" }
|
||||||
|
|
||||||
val superFqName = superClass.fqNameWhenAvailable!!.asString().replace('.', '_')
|
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 wrapperName = Name.identifier("sam$inlinePrefix\$$superFqName$SAM_WRAPPER_SUFFIX")
|
||||||
val superMethod = superClass.functions.single { it.modality == Modality.ABSTRACT }
|
val superMethod = superClass.functions.single { it.modality == Modality.ABSTRACT }
|
||||||
// TODO: have psi2ir cast the argument to the correct function type. Also see the TODO
|
// 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
|
context.ir.symbols.functionN(superMethod.valueParameters.size).owner
|
||||||
val wrappedFunctionType = wrappedFunctionClass.defaultType
|
val wrappedFunctionType = wrappedFunctionClass.defaultType
|
||||||
|
|
||||||
val wrapperVisibility = if (generatePublicWrapper) Visibilities.PUBLIC else privateGeneratedWrapperVisibility
|
|
||||||
val subclass = buildClass {
|
val subclass = buildClass {
|
||||||
name = wrapperName
|
name = wrapperName
|
||||||
origin = IrDeclarationOrigin.GENERATED_SAM_IMPLEMENTATION
|
origin = IrDeclarationOrigin.GENERATED_SAM_IMPLEMENTATION
|
||||||
|
|||||||
+8
@@ -5,14 +5,22 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.backend.js.lower
|
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.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.backend.js.JsIrBackendContext
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||||
import org.jetbrains.kotlin.ir.types.defaultType
|
import org.jetbrains.kotlin.ir.types.defaultType
|
||||||
import org.jetbrains.kotlin.ir.util.render
|
import org.jetbrains.kotlin.ir.util.render
|
||||||
|
|
||||||
class JsSingleAbstractMethodLowering(context: JsIrBackendContext) : SingleAbstractMethodLowering(context) {
|
class JsSingleAbstractMethodLowering(context: JsIrBackendContext) : SingleAbstractMethodLowering(context) {
|
||||||
|
override fun getWrapperVisibility(expression: IrTypeOperatorCall, scopes: List<ScopeWithIr>): Visibility {
|
||||||
|
return Visibilities.PRIVATE
|
||||||
|
}
|
||||||
|
|
||||||
override fun getSuperTypeForWrapper(typeOperand: IrType): IrType {
|
override fun getSuperTypeForWrapper(typeOperand: IrType): IrType {
|
||||||
// FE doesn't allow type parameters for now.
|
// FE doesn't allow type parameters for now.
|
||||||
// And since there is a to-do in common SingleAbstractMethodLowering (at function visitTypeOperator),
|
// And since there is a to-do in common SingleAbstractMethodLowering (at function visitTypeOperator),
|
||||||
|
|||||||
+6
-2
@@ -5,11 +5,13 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.jvm.lower
|
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.SingleAbstractMethodLowering
|
||||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
|
import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
|
||||||
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.descriptors.Visibility
|
import org.jetbrains.kotlin.descriptors.Visibility
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.addFunction
|
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.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrField
|
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.descriptors.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
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.IrType
|
||||||
import org.jetbrains.kotlin.ir.types.getClass
|
import org.jetbrains.kotlin.ir.types.getClass
|
||||||
import org.jetbrains.kotlin.ir.types.typeWith
|
import org.jetbrains.kotlin.ir.types.typeWith
|
||||||
@@ -35,8 +39,8 @@ internal val singleAbstractMethodPhase = makeIrFilePhase(
|
|||||||
private class JvmSingleAbstractMethodLowering(context: JvmBackendContext) : SingleAbstractMethodLowering(context) {
|
private class JvmSingleAbstractMethodLowering(context: JvmBackendContext) : SingleAbstractMethodLowering(context) {
|
||||||
private val jvmContext: JvmBackendContext get() = context as JvmBackendContext
|
private val jvmContext: JvmBackendContext get() = context as JvmBackendContext
|
||||||
|
|
||||||
override val privateGeneratedWrapperVisibility: Visibility
|
override fun getWrapperVisibility(expression: IrTypeOperatorCall, scopes: List<ScopeWithIr>) =
|
||||||
get() = JavaVisibilities.PACKAGE_VISIBILITY
|
if (inInlineFunctionScope) Visibilities.PUBLIC else JavaVisibilities.PACKAGE_VISIBILITY
|
||||||
|
|
||||||
override fun getSuperTypeForWrapper(typeOperand: IrType): IrType =
|
override fun getSuperTypeForWrapper(typeOperand: IrType): IrType =
|
||||||
typeOperand.erasedUpperBound.defaultType
|
typeOperand.erasedUpperBound.defaultType
|
||||||
|
|||||||
Reference in New Issue
Block a user