Commonize 'fun interface' handling as much as possible
TODO decide something about SamType.createByValueParameter in case of out-projected types.
This commit is contained in:
+7
-32
@@ -7,7 +7,10 @@ package org.jetbrains.kotlin.backend.jvm
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ir.createParameterDeclarations
|
||||
import org.jetbrains.kotlin.codegen.SamType
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.descriptors.annotations.FilteredAnnotations
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
@@ -15,8 +18,6 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
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.JavaSingleAbstractMethodUtils
|
||||
import org.jetbrains.kotlin.load.java.typeEnhancement.hasEnhancedNullability
|
||||
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
|
||||
@@ -24,12 +25,7 @@ import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmFieldAnnotation
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
||||
import org.jetbrains.kotlin.resolve.sam.getFunctionTypeForAbstractMethod
|
||||
import org.jetbrains.kotlin.resolve.sam.getSingleAbstractMethodOrNull
|
||||
import org.jetbrains.kotlin.synthetic.SamAdapterExtensionFunctionDescriptor
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.typeUtil.replaceAnnotations
|
||||
|
||||
class JvmGeneratorExtensions(private val generateFacades: Boolean = true) : GeneratorExtensions() {
|
||||
@@ -39,33 +35,12 @@ class JvmGeneratorExtensions(private val generateFacades: Boolean = true) : Gene
|
||||
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 =
|
||||
override fun isPlatformSamType(type: KotlinType): Boolean =
|
||||
JavaSingleAbstractMethodUtils.isSamType(type)
|
||||
|
||||
override fun getSamTypeInfoForValueParameter(valueParameter: ValueParameterDescriptor): KotlinType? {
|
||||
val samType = SamType.createByValueParameter(valueParameter) ?: return null
|
||||
return samType.type
|
||||
}
|
||||
|
||||
override fun getSubstitutedFunctionTypeForSamType(samType: KotlinType): KotlinType {
|
||||
val descriptor = samType.constructor.declarationDescriptor as? ClassDescriptor
|
||||
?: throw AssertionError("SAM should be represented by a class: $samType")
|
||||
val singleAbstractMethod = getSingleAbstractMethodOrNull(descriptor)
|
||||
?: throw AssertionError("$descriptor should have a single abstract method")
|
||||
val unsubstitutedFunctionType = getFunctionTypeForAbstractMethod(singleAbstractMethod, false)
|
||||
return TypeSubstitutor.create(samType).substitute(unsubstitutedFunctionType, Variance.INVARIANT)
|
||||
?: throw AssertionError("Failed to substitute function type $unsubstitutedFunctionType corresponding to $samType")
|
||||
}
|
||||
override fun getSamTypeForValueParameter(valueParameter: ValueParameterDescriptor): KotlinType? =
|
||||
SamType.createByValueParameter(valueParameter)?.type
|
||||
|
||||
companion object Instance : JvmSamConversion()
|
||||
}
|
||||
|
||||
+8
-10
@@ -297,7 +297,7 @@ fun StatementGenerator.generateValueArgumentUsing(
|
||||
}
|
||||
|
||||
fun StatementGenerator.castArgumentToFunctionalInterfaceForSamType(irExpression: IrExpression, samType: KotlinType): IrExpression {
|
||||
val kotlinFunctionType = context.extensions.samConversion.getSubstitutedFunctionTypeForSamType(samType)
|
||||
val kotlinFunctionType = samType.getSubstitutedFunctionTypeForSamType()
|
||||
val irFunctionType = context.typeTranslator.translateType(kotlinFunctionType)
|
||||
return irExpression.implicitCastTo(irFunctionType)
|
||||
}
|
||||
@@ -408,7 +408,7 @@ fun StatementGenerator.generateSamConversionForValueArgumentsIfRequired(call: Ca
|
||||
val samConversion = context.extensions.samConversion
|
||||
|
||||
val originalDescriptor = resolvedCall.resultingDescriptor
|
||||
val underlyingDescriptor = samConversion.getOriginalForSamAdapter(originalDescriptor) ?: originalDescriptor
|
||||
val underlyingDescriptor = originalDescriptor.getOriginalForFunctionInterfaceAdapter() ?: originalDescriptor
|
||||
|
||||
val originalValueParameters = originalDescriptor.valueParameters
|
||||
val underlyingValueParameters = underlyingDescriptor.valueParameters
|
||||
@@ -446,7 +446,8 @@ fun StatementGenerator.generateSamConversionForValueArgumentsIfRequired(call: Ca
|
||||
if (!originalValueParameters[i].type.isFunctionTypeOrSubtype) continue
|
||||
}
|
||||
|
||||
val samKotlinType = samConversion.getSamTypeInfoForValueParameter(underlyingValueParameter) ?: continue
|
||||
val samKotlinType = samConversion.getSamTypeForValueParameter(underlyingValueParameter)
|
||||
?: underlyingValueParameter.type
|
||||
|
||||
val originalArgument = call.irValueArgumentsByIndex[i] ?: continue
|
||||
|
||||
@@ -497,24 +498,21 @@ fun StatementGenerator.pregenerateCallReceivers(resolvedCall: ResolvedCall<*>):
|
||||
return call
|
||||
}
|
||||
|
||||
private fun unwrapSpecialDescriptor(
|
||||
descriptor: CallableDescriptor,
|
||||
samConversion: GeneratorExtensions.SamConversion
|
||||
): CallableDescriptor =
|
||||
private fun unwrapSpecialDescriptor(descriptor: CallableDescriptor): CallableDescriptor =
|
||||
when (descriptor) {
|
||||
is ImportedFromObjectCallableDescriptor<*> ->
|
||||
unwrapSpecialDescriptor(descriptor.callableFromObject, samConversion)
|
||||
unwrapSpecialDescriptor(descriptor.callableFromObject)
|
||||
is TypeAliasConstructorDescriptor ->
|
||||
descriptor.underlyingConstructorDescriptor
|
||||
else ->
|
||||
samConversion.getOriginalForSamAdapter(descriptor)?.let { unwrapSpecialDescriptor(it, samConversion) } ?: descriptor
|
||||
descriptor.getOriginalForFunctionInterfaceAdapter()?.let { unwrapSpecialDescriptor(it) } ?: descriptor
|
||||
}
|
||||
|
||||
fun unwrapCallableDescriptorAndTypeArguments(resolvedCall: ResolvedCall<*>, samConversion: GeneratorExtensions.SamConversion): CallBuilder {
|
||||
val originalDescriptor = resolvedCall.resultingDescriptor
|
||||
val candidateDescriptor = resolvedCall.candidateDescriptor
|
||||
|
||||
val unwrappedDescriptor = unwrapSpecialDescriptor(originalDescriptor, samConversion)
|
||||
val unwrappedDescriptor = unwrapSpecialDescriptor(originalDescriptor)
|
||||
|
||||
val originalTypeArguments = resolvedCall.typeArguments
|
||||
val unsubstitutedUnwrappedDescriptor = unwrappedDescriptor.original
|
||||
|
||||
@@ -42,7 +42,7 @@ 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.original)) {
|
||||
if (descriptor.original.isSamConstructor()) {
|
||||
return generateSamConstructorCall(descriptor, startOffset, endOffset, call)
|
||||
}
|
||||
|
||||
|
||||
+2
-11
@@ -5,7 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.psi2ir.generators
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
@@ -17,18 +16,10 @@ open class GeneratorExtensions : StubGeneratorExtensions() {
|
||||
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 isPlatformSamType(type: KotlinType): Boolean = false
|
||||
|
||||
open fun isSamType(type: KotlinType): Boolean = false
|
||||
|
||||
open fun getSamTypeInfoForValueParameter(valueParameter: ValueParameterDescriptor): KotlinType? =
|
||||
throw UnsupportedOperationException("SAM conversion is not supported in this configuration (valueParameter=$valueParameter)")
|
||||
|
||||
open fun getSubstitutedFunctionTypeForSamType(samType: KotlinType): KotlinType =
|
||||
throw UnsupportedOperationException("SAM conversion is not supported in this configuration (samType=$samType)")
|
||||
open fun getSamTypeForValueParameter(valueParameter: ValueParameterDescriptor): KotlinType? = null
|
||||
|
||||
companion object Instance : SamConversion()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
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.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.synthetic.FunctionInterfaceAdapterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.synthetic.FunctionInterfaceAdapterExtensionFunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.synthetic.FunctionInterfaceConstructorDescriptor
|
||||
import org.jetbrains.kotlin.resolve.sam.getFunctionTypeForAbstractMethod
|
||||
import org.jetbrains.kotlin.resolve.sam.getSingleAbstractMethodOrNull
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
fun GeneratorExtensions.SamConversion.isSamType(kotlinType: KotlinType): Boolean {
|
||||
val descriptor = kotlinType.constructor.declarationDescriptor
|
||||
return descriptor is ClassDescriptor && descriptor.isFun ||
|
||||
isPlatformSamType(kotlinType)
|
||||
}
|
||||
|
||||
fun DeclarationDescriptor.isSamConstructor() = this is FunctionInterfaceConstructorDescriptor
|
||||
|
||||
fun CallableDescriptor.getOriginalForFunctionInterfaceAdapter() =
|
||||
when (this) {
|
||||
is FunctionInterfaceAdapterDescriptor<*> ->
|
||||
baseDescriptorForSynthetic
|
||||
is FunctionInterfaceAdapterExtensionFunctionDescriptor ->
|
||||
baseDescriptorForSynthetic
|
||||
else ->
|
||||
null
|
||||
}
|
||||
|
||||
fun KotlinType.getSubstitutedFunctionTypeForSamType(): KotlinType {
|
||||
val descriptor = constructor.declarationDescriptor as? ClassDescriptor
|
||||
?: throw AssertionError("SAM should be represented by a class: $this")
|
||||
val singleAbstractMethod = getSingleAbstractMethodOrNull(descriptor)
|
||||
?: throw AssertionError("$descriptor should have a single abstract method")
|
||||
val unsubstitutedFunctionType = getFunctionTypeForAbstractMethod(singleAbstractMethod, false)
|
||||
return TypeSubstitutor.create(this).substitute(unsubstitutedFunctionType, Variance.INVARIANT)
|
||||
?: throw AssertionError("Failed to substitute function type $unsubstitutedFunctionType corresponding to $this")
|
||||
}
|
||||
+1
-3
@@ -43,6 +43,7 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.psi2ir.containsNull
|
||||
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
|
||||
import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions
|
||||
import org.jetbrains.kotlin.psi2ir.generators.getSubstitutedFunctionTypeForSamType
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.types.typeUtil.*
|
||||
@@ -251,9 +252,6 @@ internal class InsertImplicitCasts(
|
||||
finallyExpression = finallyExpression?.coerceToUnit()
|
||||
}
|
||||
|
||||
private fun KotlinType.getSubstitutedFunctionTypeForSamType() =
|
||||
generatorExtensions.samConversion.getSubstitutedFunctionTypeForSamType(this)
|
||||
|
||||
override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression =
|
||||
when (expression.operator) {
|
||||
IrTypeOperator.SAM_CONVERSION -> expression.transformPostfix {
|
||||
|
||||
Reference in New Issue
Block a user