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:
Dmitry Petrov
2020-01-27 16:48:06 +03:00
parent edff099ab1
commit 2d3a142786
10 changed files with 148 additions and 126 deletions
@@ -17,9 +17,10 @@
package org.jetbrains.kotlin.load.java.sam; package org.jetbrains.kotlin.load.java.sam;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor; import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
import org.jetbrains.kotlin.descriptors.synthetic.FunctionInterfaceAdapterDescriptor;
import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor; import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor;
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor; import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor;
public interface SamAdapterDescriptor<D extends FunctionDescriptor> extends FunctionDescriptor, JavaCallableMemberDescriptor, public interface SamAdapterDescriptor<D extends FunctionDescriptor>
SyntheticMemberDescriptor<D> { extends FunctionDescriptor, JavaCallableMemberDescriptor, FunctionInterfaceAdapterDescriptor<D> {
} }
@@ -21,21 +21,21 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor import org.jetbrains.kotlin.descriptors.synthetic.FunctionInterfaceConstructorDescriptor
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude
interface SamConstructorDescriptor : SimpleFunctionDescriptor, SyntheticMemberDescriptor<ClassDescriptor> interface SamConstructorDescriptor : SimpleFunctionDescriptor, FunctionInterfaceConstructorDescriptor
class SamConstructorDescriptorImpl( class SamConstructorDescriptorImpl(
containingDeclaration: DeclarationDescriptor, containingDeclaration: DeclarationDescriptor,
private val samInterface: ClassDescriptor private val samInterface: ClassDescriptor
) : SimpleFunctionDescriptorImpl( ) : SimpleFunctionDescriptorImpl(
containingDeclaration, containingDeclaration,
null, null,
samInterface.annotations, samInterface.annotations,
samInterface.name, samInterface.name,
CallableMemberDescriptor.Kind.SYNTHESIZED, CallableMemberDescriptor.Kind.SYNTHESIZED,
samInterface.source samInterface.source
), SamConstructorDescriptor { ), SamConstructorDescriptor {
override val baseDescriptorForSynthetic: ClassDescriptor override val baseDescriptorForSynthetic: ClassDescriptor
get() = samInterface get() = samInterface
@@ -22,22 +22,22 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptorImpl
import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor import org.jetbrains.kotlin.descriptors.synthetic.FunctionInterfaceAdapterExtensionFunctionDescriptor
import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.record import org.jetbrains.kotlin.incremental.record
import org.jetbrains.kotlin.resolve.sam.SamConversionResolver
import org.jetbrains.kotlin.load.java.descriptors.JavaClassConstructorDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaClassConstructorDescriptor
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
import org.jetbrains.kotlin.load.java.sam.JavaSingleAbstractMethodUtils
import org.jetbrains.kotlin.load.java.sam.SamAdapterDescriptor import org.jetbrains.kotlin.load.java.sam.SamAdapterDescriptor
import org.jetbrains.kotlin.load.java.sam.SamConstructorDescriptor import org.jetbrains.kotlin.load.java.sam.SamConstructorDescriptor
import org.jetbrains.kotlin.load.java.sam.JavaSingleAbstractMethodUtils
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.components.isVararg import org.jetbrains.kotlin.resolve.calls.components.isVararg
import org.jetbrains.kotlin.resolve.calls.inference.wrapWithCapturingSubstitution import org.jetbrains.kotlin.resolve.calls.inference.wrapWithCapturingSubstitution
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.resolve.sam.SamConversionOracle import org.jetbrains.kotlin.resolve.sam.SamConversionOracle
import org.jetbrains.kotlin.resolve.sam.SamConversionResolver
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.ResolutionScope import org.jetbrains.kotlin.resolve.scopes.ResolutionScope
import org.jetbrains.kotlin.resolve.scopes.SyntheticScope import org.jetbrains.kotlin.resolve.scopes.SyntheticScope
@@ -46,7 +46,7 @@ import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.findCorrespondingSupertype import org.jetbrains.kotlin.types.checker.findCorrespondingSupertype
import kotlin.properties.Delegates import kotlin.properties.Delegates
interface SamAdapterExtensionFunctionDescriptor : FunctionDescriptor, SyntheticMemberDescriptor<FunctionDescriptor> { interface SamAdapterExtensionFunctionDescriptor : FunctionDescriptor, FunctionInterfaceAdapterExtensionFunctionDescriptor {
override val baseDescriptorForSynthetic: FunctionDescriptor override val baseDescriptorForSynthetic: FunctionDescriptor
} }
@@ -64,33 +64,32 @@ class SamAdapterFunctionsScope(
private val shouldGenerateAdditionalSamCandidate = !samViaSyntheticScopeDisabled || shouldGenerateCandidateForVarargAfterSam private val shouldGenerateAdditionalSamCandidate = !samViaSyntheticScopeDisabled || shouldGenerateCandidateForVarargAfterSam
private val extensionForFunction = private val extensionForFunction =
storageManager.createMemoizedFunctionWithNullableValues<FunctionDescriptor, FunctionDescriptor> { function -> storageManager.createMemoizedFunctionWithNullableValues<FunctionDescriptor, FunctionDescriptor> { function ->
extensionForFunctionNotCached(function) extensionForFunctionNotCached(function)
} }
private val samAdapterForStaticFunction = private val samAdapterForStaticFunction =
storageManager.createMemoizedFunction<JavaMethodDescriptor, SamAdapterDescriptor<JavaMethodDescriptor>> { function -> storageManager.createMemoizedFunction<JavaMethodDescriptor, SamAdapterDescriptor<JavaMethodDescriptor>> { function ->
JavaSingleAbstractMethodUtils JavaSingleAbstractMethodUtils
.createSamAdapterFunction(function, samResolver, samConversionOracle) .createSamAdapterFunction(function, samResolver, samConversionOracle)
} }
private val samConstructorForClassifier = private val samConstructorForClassifier =
storageManager.createMemoizedFunction<ClassDescriptor, SamConstructorDescriptor> { classifier -> storageManager.createMemoizedFunction<ClassDescriptor, SamConstructorDescriptor> { classifier ->
JavaSingleAbstractMethodUtils JavaSingleAbstractMethodUtils
.createSamConstructorFunction(classifier.containingDeclaration, classifier, samResolver, samConversionOracle) .createSamConstructorFunction(classifier.containingDeclaration, classifier, samResolver, samConversionOracle)
} }
private val samConstructorForJavaConstructor = private val samConstructorForJavaConstructor =
storageManager.createMemoizedFunction<JavaClassConstructorDescriptor, ClassConstructorDescriptor> { constructor -> storageManager.createMemoizedFunction<JavaClassConstructorDescriptor, ClassConstructorDescriptor> { constructor ->
JavaSingleAbstractMethodUtils JavaSingleAbstractMethodUtils
.createSamAdapterConstructor(constructor, samResolver, samConversionOracle) as ClassConstructorDescriptor .createSamAdapterConstructor(constructor, samResolver, samConversionOracle) as ClassConstructorDescriptor
} }
private val samConstructorForTypeAliasConstructor = private val samConstructorForTypeAliasConstructor =
storageManager.createMemoizedFunctionWithNullableValues<Pair<ClassConstructorDescriptor, TypeAliasDescriptor>, TypeAliasConstructorDescriptor> { storageManager.createMemoizedFunctionWithNullableValues<Pair<ClassConstructorDescriptor, TypeAliasDescriptor>, TypeAliasConstructorDescriptor> { (constructor, typeAliasDescriptor) ->
(constructor, typeAliasDescriptor) -> TypeAliasConstructorDescriptorImpl.createIfAvailable(storageManager, typeAliasDescriptor, constructor)
TypeAliasConstructorDescriptorImpl.createIfAvailable(storageManager, typeAliasDescriptor, constructor) }
}
private fun extensionForFunctionNotCached(function: FunctionDescriptor): FunctionDescriptor? { private fun extensionForFunctionNotCached(function: FunctionDescriptor): FunctionDescriptor? {
if (!function.visibility.isVisibleOutside()) return null if (!function.visibility.isVisibleOutside()) return null
@@ -144,10 +143,10 @@ class SamAdapterFunctionsScope(
val correspondingSupertype = findCorrespondingSupertype(receiverType, containingClass.defaultType) ?: return null val correspondingSupertype = findCorrespondingSupertype(receiverType, containingClass.defaultType) ?: return null
return substitute( return substitute(
TypeConstructorSubstitution TypeConstructorSubstitution
.create(correspondingSupertype) .create(correspondingSupertype)
.wrapWithCapturingSubstitution(needApproximation = true) .wrapWithCapturingSubstitution(needApproximation = true)
.buildSubstitutor() .buildSubstitutor()
) )
} }
@@ -225,8 +224,8 @@ class SamAdapterFunctionsScope(
} }
private fun getSamFunctions( private fun getSamFunctions(
functions: Collection<DeclarationDescriptor>, functions: Collection<DeclarationDescriptor>,
location: LookupLocation? location: LookupLocation?
): List<SamAdapterDescriptor<JavaMethodDescriptor>> { ): List<SamAdapterDescriptor<JavaMethodDescriptor>> {
if (!shouldGenerateAdditionalSamCandidate) return emptyList() if (!shouldGenerateAdditionalSamCandidate) return emptyList()
@@ -274,18 +273,19 @@ class SamAdapterFunctionsScope(
if (!JavaSingleAbstractMethodUtils.isSamClassDescriptor(classDescriptor)) return null if (!JavaSingleAbstractMethodUtils.isSamClassDescriptor(classDescriptor)) return null
return JavaSingleAbstractMethodUtils.createTypeAliasSamConstructorFunction( return JavaSingleAbstractMethodUtils.createTypeAliasSamConstructorFunction(
classifier, samConstructorForClassifier(classDescriptor), samResolver, samConversionOracle classifier, samConstructorForClassifier(classDescriptor), samResolver, samConversionOracle
) )
} }
private class SamAdapterExtensionFunctionDescriptorImpl( private class SamAdapterExtensionFunctionDescriptorImpl(
containingDeclaration: DeclarationDescriptor, containingDeclaration: DeclarationDescriptor,
original: SimpleFunctionDescriptor?, original: SimpleFunctionDescriptor?,
annotations: Annotations, annotations: Annotations,
name: Name, name: Name,
kind: CallableMemberDescriptor.Kind, kind: CallableMemberDescriptor.Kind,
source: SourceElement source: SourceElement
) : SamAdapterExtensionFunctionDescriptor, SimpleFunctionDescriptorImpl(containingDeclaration, original, annotations, name, kind, source) { ) : SamAdapterExtensionFunctionDescriptor,
SimpleFunctionDescriptorImpl(containingDeclaration, original, annotations, name, kind, source) {
override var baseDescriptorForSynthetic: FunctionDescriptor by Delegates.notNull() override var baseDescriptorForSynthetic: FunctionDescriptor by Delegates.notNull()
private set private set
@@ -301,29 +301,33 @@ class SamAdapterFunctionsScope(
samConversionOracle: SamConversionOracle samConversionOracle: SamConversionOracle
): SamAdapterExtensionFunctionDescriptorImpl { ): SamAdapterExtensionFunctionDescriptorImpl {
val descriptor = SamAdapterExtensionFunctionDescriptorImpl( val descriptor = SamAdapterExtensionFunctionDescriptorImpl(
sourceFunction.containingDeclaration, sourceFunction.containingDeclaration,
null, null,
sourceFunction.annotations, sourceFunction.annotations,
sourceFunction.name, sourceFunction.name,
CallableMemberDescriptor.Kind.SYNTHESIZED, CallableMemberDescriptor.Kind.SYNTHESIZED,
sourceFunction.original.source) sourceFunction.original.source
)
descriptor.baseDescriptorForSynthetic = sourceFunction descriptor.baseDescriptorForSynthetic = sourceFunction
val sourceTypeParams = (sourceFunction.typeParameters).toMutableList() val sourceTypeParams = (sourceFunction.typeParameters).toMutableList()
val ownerClass = sourceFunction.containingDeclaration as ClassDescriptor val ownerClass = sourceFunction.containingDeclaration as ClassDescriptor
val typeParameters = ArrayList<TypeParameterDescriptor>(sourceTypeParams.size) val typeParameters = ArrayList<TypeParameterDescriptor>(sourceTypeParams.size)
val typeSubstitutor = DescriptorSubstitutor.substituteTypeParameters(sourceTypeParams, TypeSubstitution.EMPTY, descriptor, typeParameters) val typeSubstitutor =
DescriptorSubstitutor.substituteTypeParameters(sourceTypeParams, TypeSubstitution.EMPTY, descriptor, typeParameters)
val returnType = typeSubstitutor.safeSubstitute(sourceFunction.returnType!!, Variance.INVARIANT) val returnType = typeSubstitutor.safeSubstitute(sourceFunction.returnType!!, Variance.INVARIANT)
val valueParameters = JavaSingleAbstractMethodUtils.createValueParametersForSamAdapter( val valueParameters = JavaSingleAbstractMethodUtils.createValueParametersForSamAdapter(
sourceFunction, descriptor, typeSubstitutor, samResolver, samConversionOracle sourceFunction, descriptor, typeSubstitutor, samResolver, samConversionOracle
) )
val visibility = syntheticVisibility(sourceFunction, isUsedForExtension = false) val visibility = syntheticVisibility(sourceFunction, isUsedForExtension = false)
descriptor.initialize(null, ownerClass.thisAsReceiverParameter, typeParameters, valueParameters, returnType, descriptor.initialize(
Modality.FINAL, visibility) null, ownerClass.thisAsReceiverParameter, typeParameters, valueParameters, returnType,
Modality.FINAL, visibility
)
descriptor.isOperator = sourceFunction.isOperator descriptor.isOperator = sourceFunction.isOperator
descriptor.isInfix = sourceFunction.isInfix descriptor.isInfix = sourceFunction.isInfix
@@ -336,33 +340,33 @@ class SamAdapterFunctionsScope(
override fun hasSynthesizedParameterNames() = baseDescriptorForSynthetic.hasSynthesizedParameterNames() override fun hasSynthesizedParameterNames() = baseDescriptorForSynthetic.hasSynthesizedParameterNames()
override fun createSubstitutedCopy( override fun createSubstitutedCopy(
newOwner: DeclarationDescriptor, newOwner: DeclarationDescriptor,
original: FunctionDescriptor?, original: FunctionDescriptor?,
kind: CallableMemberDescriptor.Kind, kind: CallableMemberDescriptor.Kind,
newName: Name?, newName: Name?,
annotations: Annotations, annotations: Annotations,
source: SourceElement source: SourceElement
): SamAdapterExtensionFunctionDescriptorImpl { ): SamAdapterExtensionFunctionDescriptorImpl {
return SamAdapterExtensionFunctionDescriptorImpl( return SamAdapterExtensionFunctionDescriptorImpl(
containingDeclaration, original as SimpleFunctionDescriptor?, annotations, newName ?: name, kind, source containingDeclaration, original as SimpleFunctionDescriptor?, annotations, newName ?: name, kind, source
).apply { ).apply {
baseDescriptorForSynthetic = this@SamAdapterExtensionFunctionDescriptorImpl.baseDescriptorForSynthetic baseDescriptorForSynthetic = this@SamAdapterExtensionFunctionDescriptorImpl.baseDescriptorForSynthetic
} }
} }
override fun newCopyBuilder(substitutor: TypeSubstitutor): CopyConfiguration = override fun newCopyBuilder(substitutor: TypeSubstitutor): CopyConfiguration =
super.newCopyBuilder(substitutor).setOriginal(this.original) super.newCopyBuilder(substitutor).setOriginal(this.original)
override fun doSubstitute(configuration: CopyConfiguration): FunctionDescriptor? { override fun doSubstitute(configuration: CopyConfiguration): FunctionDescriptor? {
val descriptor = super.doSubstitute(configuration) as SamAdapterExtensionFunctionDescriptorImpl? ?: return null val descriptor = super.doSubstitute(configuration) as SamAdapterExtensionFunctionDescriptorImpl? ?: return null
val original = configuration.original val original = configuration.original
?: throw UnsupportedOperationException("doSubstitute with no original should not be called for synthetic extension $this") ?: throw UnsupportedOperationException("doSubstitute with no original should not be called for synthetic extension $this")
original as SamAdapterExtensionFunctionDescriptorImpl original as SamAdapterExtensionFunctionDescriptorImpl
assert(original.original == original) { "original in doSubstitute should have no other original" } assert(original.original == original) { "original in doSubstitute should have no other original" }
val sourceFunctionSubstitutor = val sourceFunctionSubstitutor =
CompositionTypeSubstitution(configuration.substitution, fromSourceFunctionTypeParameters).buildSubstitutor() CompositionTypeSubstitution(configuration.substitution, fromSourceFunctionTypeParameters).buildSubstitutor()
descriptor.baseDescriptorForSynthetic = original.baseDescriptorForSynthetic.substitute(sourceFunctionSubstitutor) ?: return null descriptor.baseDescriptorForSynthetic = original.baseDescriptorForSynthetic.substitute(sourceFunctionSubstitutor) ?: return null
return descriptor return descriptor
@@ -7,7 +7,10 @@ package org.jetbrains.kotlin.backend.jvm
import org.jetbrains.kotlin.backend.common.ir.createParameterDeclarations import org.jetbrains.kotlin.backend.common.ir.createParameterDeclarations
import org.jetbrains.kotlin.codegen.SamType 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.descriptors.annotations.FilteredAnnotations
import org.jetbrains.kotlin.ir.builders.declarations.buildClass import org.jetbrains.kotlin.ir.builders.declarations.buildClass
import org.jetbrains.kotlin.ir.declarations.IrClass 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.JvmAnnotationNames
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor 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.sam.JavaSingleAbstractMethodUtils
import org.jetbrains.kotlin.load.java.typeEnhancement.hasEnhancedNullability import org.jetbrains.kotlin.load.java.typeEnhancement.hasEnhancedNullability
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource 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.JvmClassName
import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmFieldAnnotation import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmFieldAnnotation
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource 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.KotlinType
import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.typeUtil.replaceAnnotations import org.jetbrains.kotlin.types.typeUtil.replaceAnnotations
class JvmGeneratorExtensions(private val generateFacades: Boolean = true) : GeneratorExtensions() { class JvmGeneratorExtensions(private val generateFacades: Boolean = true) : GeneratorExtensions() {
@@ -39,33 +35,12 @@ class JvmGeneratorExtensions(private val generateFacades: Boolean = true) : Gene
get() = JvmSamConversion get() = JvmSamConversion
open class JvmSamConversion : SamConversion() { 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 = override fun isPlatformSamType(type: KotlinType): Boolean =
descriptor is SamConstructorDescriptor
override fun isSamType(type: KotlinType): Boolean =
JavaSingleAbstractMethodUtils.isSamType(type) JavaSingleAbstractMethodUtils.isSamType(type)
override fun getSamTypeInfoForValueParameter(valueParameter: ValueParameterDescriptor): KotlinType? { override fun getSamTypeForValueParameter(valueParameter: ValueParameterDescriptor): KotlinType? =
val samType = SamType.createByValueParameter(valueParameter) ?: return null SamType.createByValueParameter(valueParameter)?.type
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")
}
companion object Instance : JvmSamConversion() companion object Instance : JvmSamConversion()
} }
@@ -297,7 +297,7 @@ fun StatementGenerator.generateValueArgumentUsing(
} }
fun StatementGenerator.castArgumentToFunctionalInterfaceForSamType(irExpression: IrExpression, samType: KotlinType): IrExpression { 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) val irFunctionType = context.typeTranslator.translateType(kotlinFunctionType)
return irExpression.implicitCastTo(irFunctionType) return irExpression.implicitCastTo(irFunctionType)
} }
@@ -408,7 +408,7 @@ fun StatementGenerator.generateSamConversionForValueArgumentsIfRequired(call: Ca
val samConversion = context.extensions.samConversion val samConversion = context.extensions.samConversion
val originalDescriptor = resolvedCall.resultingDescriptor val originalDescriptor = resolvedCall.resultingDescriptor
val underlyingDescriptor = samConversion.getOriginalForSamAdapter(originalDescriptor) ?: originalDescriptor val underlyingDescriptor = originalDescriptor.getOriginalForFunctionInterfaceAdapter() ?: originalDescriptor
val originalValueParameters = originalDescriptor.valueParameters val originalValueParameters = originalDescriptor.valueParameters
val underlyingValueParameters = underlyingDescriptor.valueParameters val underlyingValueParameters = underlyingDescriptor.valueParameters
@@ -446,7 +446,8 @@ fun StatementGenerator.generateSamConversionForValueArgumentsIfRequired(call: Ca
if (!originalValueParameters[i].type.isFunctionTypeOrSubtype) continue 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 val originalArgument = call.irValueArgumentsByIndex[i] ?: continue
@@ -497,24 +498,21 @@ fun StatementGenerator.pregenerateCallReceivers(resolvedCall: ResolvedCall<*>):
return call return call
} }
private fun unwrapSpecialDescriptor( private fun unwrapSpecialDescriptor(descriptor: CallableDescriptor): CallableDescriptor =
descriptor: CallableDescriptor,
samConversion: GeneratorExtensions.SamConversion
): CallableDescriptor =
when (descriptor) { when (descriptor) {
is ImportedFromObjectCallableDescriptor<*> -> is ImportedFromObjectCallableDescriptor<*> ->
unwrapSpecialDescriptor(descriptor.callableFromObject, samConversion) unwrapSpecialDescriptor(descriptor.callableFromObject)
is TypeAliasConstructorDescriptor -> is TypeAliasConstructorDescriptor ->
descriptor.underlyingConstructorDescriptor descriptor.underlyingConstructorDescriptor
else -> else ->
samConversion.getOriginalForSamAdapter(descriptor)?.let { unwrapSpecialDescriptor(it, samConversion) } ?: descriptor descriptor.getOriginalForFunctionInterfaceAdapter()?.let { unwrapSpecialDescriptor(it) } ?: descriptor
} }
fun unwrapCallableDescriptorAndTypeArguments(resolvedCall: ResolvedCall<*>, samConversion: GeneratorExtensions.SamConversion): CallBuilder { fun unwrapCallableDescriptorAndTypeArguments(resolvedCall: ResolvedCall<*>, samConversion: GeneratorExtensions.SamConversion): CallBuilder {
val originalDescriptor = resolvedCall.resultingDescriptor val originalDescriptor = resolvedCall.resultingDescriptor
val candidateDescriptor = resolvedCall.candidateDescriptor val candidateDescriptor = resolvedCall.candidateDescriptor
val unwrappedDescriptor = unwrapSpecialDescriptor(originalDescriptor, samConversion) val unwrappedDescriptor = unwrapSpecialDescriptor(originalDescriptor)
val originalTypeArguments = resolvedCall.typeArguments val originalTypeArguments = resolvedCall.typeArguments
val unsubstitutedUnwrappedDescriptor = unwrappedDescriptor.original 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 { fun generateCall(startOffset: Int, endOffset: Int, call: CallBuilder, origin: IrStatementOrigin? = null): IrExpression {
val descriptor = call.descriptor val descriptor = call.descriptor
if (context.extensions.samConversion.isSamConstructor(descriptor.original)) { if (descriptor.original.isSamConstructor()) {
return generateSamConstructorCall(descriptor, startOffset, endOffset, call) return generateSamConstructorCall(descriptor, startOffset, endOffset, call)
} }
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.psi2ir.generators package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.descriptors.Visibility
@@ -17,18 +16,10 @@ open class GeneratorExtensions : StubGeneratorExtensions() {
get() = SamConversion get() = SamConversion
open class 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 getSamTypeForValueParameter(valueParameter: ValueParameterDescriptor): KotlinType? = null
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)")
companion object Instance : SamConversion() 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")
}
@@ -43,6 +43,7 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.psi2ir.containsNull import org.jetbrains.kotlin.psi2ir.containsNull
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions
import org.jetbrains.kotlin.psi2ir.generators.getSubstitutedFunctionTypeForSamType
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.types.typeUtil.* import org.jetbrains.kotlin.types.typeUtil.*
@@ -251,9 +252,6 @@ internal class InsertImplicitCasts(
finallyExpression = finallyExpression?.coerceToUnit() finallyExpression = finallyExpression?.coerceToUnit()
} }
private fun KotlinType.getSubstitutedFunctionTypeForSamType() =
generatorExtensions.samConversion.getSubstitutedFunctionTypeForSamType(this)
override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression = override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression =
when (expression.operator) { when (expression.operator) {
IrTypeOperator.SAM_CONVERSION -> expression.transformPostfix { IrTypeOperator.SAM_CONVERSION -> expression.transformPostfix {
@@ -16,8 +16,16 @@
package org.jetbrains.kotlin.descriptors.synthetic package org.jetbrains.kotlin.descriptors.synthetic
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
interface SyntheticMemberDescriptor<out T : DeclarationDescriptor> { interface SyntheticMemberDescriptor<out T : DeclarationDescriptor> {
val baseDescriptorForSynthetic: T val baseDescriptorForSynthetic: T
} }
interface FunctionInterfaceConstructorDescriptor : SyntheticMemberDescriptor<ClassDescriptor>
interface FunctionInterfaceAdapterDescriptor<out T : FunctionDescriptor> : SyntheticMemberDescriptor<T>
interface FunctionInterfaceAdapterExtensionFunctionDescriptor : SyntheticMemberDescriptor<FunctionDescriptor>