Do not use JVM-specific code for SAM conversions in psi2ir
Extract all JVM-specific code into GeneratorExtensions.SamConversion. This is needed in order to remove dependency of ir.tree on frontend.java
This commit is contained in:
+39
@@ -5,10 +5,18 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||
import org.jetbrains.kotlin.load.java.sam.SamAdapterDescriptor
|
||||
import org.jetbrains.kotlin.load.java.sam.SamConstructorDescriptor
|
||||
import org.jetbrains.kotlin.load.java.sam.SingleAbstractMethodUtils
|
||||
import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions
|
||||
import org.jetbrains.kotlin.synthetic.SamAdapterExtensionFunctionDescriptor
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
object JvmGeneratorExtensions : GeneratorExtensions() {
|
||||
override val externalDeclarationOrigin: ((DeclarationDescriptor) -> IrDeclarationOrigin)? = { descriptor ->
|
||||
@@ -17,4 +25,35 @@ object JvmGeneratorExtensions : GeneratorExtensions() {
|
||||
else
|
||||
IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB
|
||||
}
|
||||
|
||||
override val samConversion: SamConversion
|
||||
get() = JvmSamConversion
|
||||
|
||||
open class JvmSamConversion : SamConversion() {
|
||||
override fun getOriginalForSamAdapter(descriptor: CallableDescriptor): CallableDescriptor? =
|
||||
when (descriptor) {
|
||||
is SamAdapterDescriptor<*> -> descriptor.baseDescriptorForSynthetic
|
||||
is SamAdapterExtensionFunctionDescriptor -> descriptor.baseDescriptorForSynthetic
|
||||
else -> null
|
||||
}
|
||||
|
||||
override fun isSamConstructor(descriptor: CallableDescriptor): Boolean =
|
||||
descriptor is SamConstructorDescriptor
|
||||
|
||||
override fun isSamType(type: KotlinType): Boolean =
|
||||
SingleAbstractMethodUtils.isSamType(type)
|
||||
|
||||
override fun getFunctionTypeForSAMClass(descriptor: ClassDescriptor): KotlinType {
|
||||
if (descriptor !is JavaClassDescriptor) {
|
||||
throw AssertionError("SAM should be represented by a Java class: $descriptor")
|
||||
}
|
||||
|
||||
val singleAbstractMethod = SingleAbstractMethodUtils.getSingleAbstractMethodOrNull(descriptor)
|
||||
?: throw AssertionError("$descriptor should have a single abstract method")
|
||||
|
||||
return SingleAbstractMethodUtils.getFunctionTypeForAbstractMethod(singleAbstractMethod, false)
|
||||
}
|
||||
|
||||
companion object Instance : JvmSamConversion()
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.backend.common.utils.isSubtypeOf
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmGeneratorExtensions
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
@@ -27,7 +28,8 @@ internal val jvmCoercionToUnitPhase = makeIrFilePhase(
|
||||
class JvmCoercionToUnitPatcher(val context: JvmBackendContext) :
|
||||
InsertImplicitCasts(
|
||||
context.builtIns, context.irBuiltIns,
|
||||
TypeTranslator(context.ir.symbols.externalSymbolTable, context.state.languageVersionSettings)
|
||||
TypeTranslator(context.ir.symbols.externalSymbolTable, context.state.languageVersionSettings),
|
||||
JvmGeneratorExtensions.samConversion
|
||||
),
|
||||
FileLoweringPass {
|
||||
|
||||
@@ -42,4 +44,4 @@ class JvmCoercionToUnitPatcher(val context: JvmBackendContext) :
|
||||
|
||||
return this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-19
@@ -28,8 +28,6 @@ import org.jetbrains.kotlin.ir.expressions.IrExpressionWithCopy
|
||||
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||
import org.jetbrains.kotlin.load.java.sam.SamAdapterDescriptor
|
||||
import org.jetbrains.kotlin.load.java.sam.SingleAbstractMethodUtils
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
@@ -42,7 +40,6 @@ import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getSuperCallExpressio
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.*
|
||||
import org.jetbrains.kotlin.synthetic.SamAdapterExtensionFunctionDescriptor
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
|
||||
@@ -383,11 +380,7 @@ private fun StatementGenerator.pregenerateValueArguments(call: CallBuilder, reso
|
||||
}
|
||||
|
||||
private fun StatementGenerator.generateSamConversionForValueArgumentsIfRequired(call: CallBuilder, originalDescriptor: CallableDescriptor) {
|
||||
val underlyingDescriptor = when (originalDescriptor) {
|
||||
is SamAdapterDescriptor<*> -> originalDescriptor.baseDescriptorForSynthetic
|
||||
is SamAdapterExtensionFunctionDescriptor -> originalDescriptor.baseDescriptorForSynthetic
|
||||
else -> return
|
||||
}
|
||||
val underlyingDescriptor = context.extensions.samConversion.getOriginalForSamAdapter(originalDescriptor) ?: return
|
||||
|
||||
val originalValueParameters = originalDescriptor.valueParameters
|
||||
val underlyingValueParameters = underlyingDescriptor.valueParameters
|
||||
@@ -405,7 +398,7 @@ private fun StatementGenerator.generateSamConversionForValueArgumentsIfRequired(
|
||||
val originalParameterType = originalValueParameters[i].type
|
||||
val underlyingParameterType = underlyingValueParameters[i].type
|
||||
|
||||
if (!SingleAbstractMethodUtils.isSamType(underlyingParameterType)) continue
|
||||
if (!context.extensions.samConversion.isSamType(underlyingParameterType)) continue
|
||||
if (!originalParameterType.isFunctionTypeOrSubtype) continue
|
||||
|
||||
val originalArgument = call.irValueArgumentsByIndex[i] ?: continue
|
||||
@@ -437,7 +430,7 @@ fun StatementGenerator.pregenerateValueArgumentsUsing(
|
||||
}
|
||||
|
||||
fun StatementGenerator.pregenerateCallReceivers(resolvedCall: ResolvedCall<*>): CallBuilder {
|
||||
val call = unwrapCallableDescriptorAndTypeArguments(resolvedCall)
|
||||
val call = unwrapCallableDescriptorAndTypeArguments(resolvedCall, context.extensions.samConversion)
|
||||
|
||||
call.callReceiver = generateCallReceiver(
|
||||
resolvedCall.call.callElement,
|
||||
@@ -452,20 +445,21 @@ fun StatementGenerator.pregenerateCallReceivers(resolvedCall: ResolvedCall<*>):
|
||||
return call
|
||||
}
|
||||
|
||||
private fun unwrapSpecialDescriptor(originalDescriptor: CallableDescriptor): CallableDescriptor =
|
||||
when (originalDescriptor) {
|
||||
is ImportedFromObjectCallableDescriptor<*> -> unwrapSpecialDescriptor(originalDescriptor.callableFromObject)
|
||||
is TypeAliasConstructorDescriptor -> originalDescriptor.underlyingConstructorDescriptor
|
||||
is SamAdapterDescriptor<*> -> unwrapSpecialDescriptor(originalDescriptor.baseDescriptorForSynthetic)
|
||||
is SamAdapterExtensionFunctionDescriptor -> unwrapSpecialDescriptor(originalDescriptor.baseDescriptorForSynthetic)
|
||||
else -> originalDescriptor
|
||||
private fun unwrapSpecialDescriptor(
|
||||
descriptor: CallableDescriptor,
|
||||
samConversion: GeneratorExtensions.SamConversion
|
||||
): CallableDescriptor =
|
||||
when (descriptor) {
|
||||
is ImportedFromObjectCallableDescriptor<*> -> unwrapSpecialDescriptor(descriptor.callableFromObject, samConversion)
|
||||
is TypeAliasConstructorDescriptor -> descriptor.underlyingConstructorDescriptor
|
||||
else -> samConversion.getOriginalForSamAdapter(descriptor)?.let { unwrapSpecialDescriptor(it, samConversion) } ?: descriptor
|
||||
}
|
||||
|
||||
fun unwrapCallableDescriptorAndTypeArguments(resolvedCall: ResolvedCall<*>): CallBuilder {
|
||||
fun unwrapCallableDescriptorAndTypeArguments(resolvedCall: ResolvedCall<*>, samConversion: GeneratorExtensions.SamConversion): CallBuilder {
|
||||
val originalDescriptor = resolvedCall.resultingDescriptor
|
||||
val candidateDescriptor = resolvedCall.candidateDescriptor
|
||||
|
||||
val unwrappedDescriptor = unwrapSpecialDescriptor(originalDescriptor)
|
||||
val unwrappedDescriptor = unwrapSpecialDescriptor(originalDescriptor, samConversion)
|
||||
|
||||
val originalTypeArguments = resolvedCall.typeArguments
|
||||
val unsubstitutedUnwrappedDescriptor = unwrappedDescriptor.original
|
||||
|
||||
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.ir.types.IrDynamicType
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||
import org.jetbrains.kotlin.ir.util.referenceFunction
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.load.java.sam.SamConstructorDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
|
||||
@@ -44,9 +43,11 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
||||
fun generateCall(startOffset: Int, endOffset: Int, call: CallBuilder, origin: IrStatementOrigin? = null): IrExpression {
|
||||
val descriptor = call.descriptor
|
||||
|
||||
if (context.extensions.samConversion.isSamConstructor(descriptor)) {
|
||||
return generateSamConstructorCall(descriptor, startOffset, endOffset, call)
|
||||
}
|
||||
|
||||
return when (descriptor) {
|
||||
is SamConstructorDescriptor ->
|
||||
generateSamConstructorCall(descriptor, startOffset, endOffset, call)
|
||||
is PropertyDescriptor ->
|
||||
generatePropertyGetterCall(descriptor, startOffset, endOffset, call)
|
||||
is FunctionDescriptor ->
|
||||
@@ -59,7 +60,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
||||
}
|
||||
|
||||
private fun generateSamConstructorCall(
|
||||
descriptor: SamConstructorDescriptor,
|
||||
descriptor: CallableDescriptor,
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
call: CallBuilder
|
||||
|
||||
+20
@@ -5,10 +5,30 @@
|
||||
|
||||
package org.jetbrains.kotlin.psi2ir.generators
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
open class GeneratorExtensions {
|
||||
open val externalDeclarationOrigin: ((DeclarationDescriptor) -> IrDeclarationOrigin)?
|
||||
get() = null
|
||||
|
||||
open val samConversion: SamConversion
|
||||
get() = SamConversion
|
||||
|
||||
open class SamConversion {
|
||||
// Returns null if descriptor is not a SAM adapter
|
||||
open fun getOriginalForSamAdapter(descriptor: CallableDescriptor): CallableDescriptor? = null
|
||||
|
||||
open fun isSamConstructor(descriptor: CallableDescriptor): Boolean = false
|
||||
|
||||
open fun isSamType(type: KotlinType): Boolean = false
|
||||
|
||||
open fun getFunctionTypeForSAMClass(descriptor: ClassDescriptor): KotlinType =
|
||||
throw UnsupportedOperationException("SAM conversion is not supported in this configuration (class=$descriptor)")
|
||||
|
||||
companion object Instance : SamConversion()
|
||||
}
|
||||
}
|
||||
|
||||
+11
-12
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.psi2ir.transformations
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
@@ -33,10 +34,9 @@ import org.jetbrains.kotlin.ir.util.TypeTranslator
|
||||
import org.jetbrains.kotlin.ir.util.coerceToUnitIfNeeded
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||
import org.jetbrains.kotlin.load.java.sam.SingleAbstractMethodUtils
|
||||
import org.jetbrains.kotlin.psi2ir.containsNull
|
||||
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
|
||||
import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNullableAny
|
||||
@@ -45,13 +45,17 @@ import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||
|
||||
fun insertImplicitCasts(element: IrElement, context: GeneratorContext) {
|
||||
element.transformChildren(InsertImplicitCasts(context.builtIns, context.irBuiltIns, context.typeTranslator), null)
|
||||
element.transformChildren(
|
||||
InsertImplicitCasts(context.builtIns, context.irBuiltIns, context.typeTranslator, context.extensions.samConversion),
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
open class InsertImplicitCasts(
|
||||
private val builtIns: KotlinBuiltIns,
|
||||
private val irBuiltIns: IrBuiltIns,
|
||||
private val typeTranslator: TypeTranslator
|
||||
private val typeTranslator: TypeTranslator,
|
||||
private val samConversion: GeneratorExtensions.SamConversion
|
||||
) : IrElementTransformerVoid() {
|
||||
|
||||
private fun KotlinType.toIrType() = typeTranslator.translateType(this)
|
||||
@@ -177,15 +181,10 @@ open class InsertImplicitCasts(
|
||||
super.visitTypeOperator(expression)
|
||||
|
||||
private fun IrTypeOperatorCall.coerceArgumentToFunctionalType(): IrExpression {
|
||||
val targetClassDescriptor = typeOperandClassifier.descriptor as? JavaClassDescriptor
|
||||
?: throw AssertionError("Target type of $operator should be a Java class: ${render()}")
|
||||
val targetClassDescriptor = typeOperandClassifier.descriptor as? ClassDescriptor
|
||||
?: throw AssertionError("Target type of $operator should be a class: ${render()}")
|
||||
|
||||
val singleAbstractMethod = SingleAbstractMethodUtils.getSingleAbstractMethodOrNull(targetClassDescriptor)
|
||||
?: throw AssertionError("$targetClassDescriptor should have a single abstract method")
|
||||
|
||||
val functionalType = SingleAbstractMethodUtils.getFunctionTypeForAbstractMethod(singleAbstractMethod, false)
|
||||
|
||||
argument = argument.cast(functionalType)
|
||||
argument = argument.cast(samConversion.getFunctionTypeForSAMClass(targetClassDescriptor))
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user