diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/JavaSingleAbstractMethodUtils.java b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/JavaSingleAbstractMethodUtils.java index 22b92eca5b6..e1104e87ae5 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/JavaSingleAbstractMethodUtils.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/JavaSingleAbstractMethodUtils.java @@ -17,104 +17,23 @@ package org.jetbrains.kotlin.load.java.sam; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.descriptors.*; -import org.jetbrains.kotlin.descriptors.annotations.Annotations; -import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl; -import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl; import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl; import org.jetbrains.kotlin.load.java.descriptors.JavaClassConstructorDescriptor; import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor; import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaClassDescriptor; -import org.jetbrains.kotlin.name.Name; -import org.jetbrains.kotlin.resolve.jvm.JavaResolverUtils; import org.jetbrains.kotlin.resolve.sam.*; import org.jetbrains.kotlin.types.KotlinType; -import org.jetbrains.kotlin.types.SimpleType; import org.jetbrains.kotlin.types.TypeSubstitutor; import org.jetbrains.kotlin.types.Variance; import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import java.util.Map; public class JavaSingleAbstractMethodUtils { private JavaSingleAbstractMethodUtils() { } - @NotNull - public static SamConstructorDescriptor createSamConstructorFunction( - @NotNull DeclarationDescriptor owner, - @NotNull ClassDescriptor samInterface, - @NotNull SamConversionResolver samResolver, - @NotNull SamConversionOracle samConversionOracle - ) { - assert SamConversionResolverImplKt.getSingleAbstractMethodOrNull(samInterface) != null : samInterface; - - SamConstructorDescriptorImpl result = new SamConstructorDescriptorImpl(owner, samInterface); - - List samTypeParameters = samInterface.getTypeConstructor().getParameters(); - SimpleType unsubstitutedSamType = samInterface.getDefaultType(); - initializeSamConstructorDescriptor(samInterface, result, samTypeParameters, unsubstitutedSamType, samResolver, samConversionOracle); - - return result; - } - - private static void initializeSamConstructorDescriptor( - @NotNull ClassDescriptor samInterface, - @NotNull SimpleFunctionDescriptorImpl samConstructor, - @NotNull List samTypeParameters, - @NotNull KotlinType unsubstitutedSamType, - @NotNull SamConversionResolver samResolver, - @NotNull SamConversionOracle samConversionOracle - ) { - TypeParameters typeParameters = recreateAndInitializeTypeParameters(samTypeParameters, samConstructor); - - KotlinType parameterTypeUnsubstituted = - SamConversionResolverImplKt.getFunctionTypeForSamType(unsubstitutedSamType, samResolver, samConversionOracle); - assert parameterTypeUnsubstituted != null : "couldn't get function type for SAM type " + unsubstitutedSamType; - KotlinType parameterType = typeParameters.substitutor.substitute(parameterTypeUnsubstituted, Variance.IN_VARIANCE); - assert parameterType != null : "couldn't substitute type: " + parameterTypeUnsubstituted + - ", substitutor = " + typeParameters.substitutor; - ValueParameterDescriptor parameter = new ValueParameterDescriptorImpl( - samConstructor, null, 0, Annotations.Companion.getEMPTY(), Name.identifier("function"), parameterType, - /* declaresDefaultValue = */ false, - /* isCrossinline = */ false, - /* isNoinline = */ false, - null, SourceElement.NO_SOURCE); - - KotlinType returnType = typeParameters.substitutor.substitute(unsubstitutedSamType, Variance.OUT_VARIANCE); - assert returnType != null : "couldn't substitute type: " + unsubstitutedSamType + - ", substitutor = " + typeParameters.substitutor; - - samConstructor.initialize( - null, - null, - typeParameters.descriptors, - Collections.singletonList(parameter), - returnType, - Modality.FINAL, - samInterface.getVisibility() - ); - } - - public static SamConstructorDescriptor createTypeAliasSamConstructorFunction( - @NotNull TypeAliasDescriptor typeAliasDescriptor, - @NotNull SamConstructorDescriptor underlyingSamConstructor, - @NotNull SamConversionResolver samResolver, - @NotNull SamConversionOracle samConversionOracle - ) { - SamTypeAliasConstructorDescriptorImpl result = new SamTypeAliasConstructorDescriptorImpl(typeAliasDescriptor, underlyingSamConstructor); - - ClassDescriptor samInterface = underlyingSamConstructor.getBaseDescriptorForSynthetic(); - List samTypeParameters = typeAliasDescriptor.getTypeConstructor().getParameters(); - SimpleType unsubstitutedSamType = typeAliasDescriptor.getExpandedType(); - initializeSamConstructorDescriptor(samInterface, result, samTypeParameters, unsubstitutedSamType, samResolver, samConversionOracle); - - return result; - } - public static boolean isSamClassDescriptor(@NotNull ClassDescriptor descriptor) { if (descriptor.isFun()) return true; if (descriptor instanceof LazyJavaClassDescriptor && descriptor.getDefaultFunctionTypeForSamInterface() != null) return true; @@ -195,17 +114,17 @@ public class JavaSingleAbstractMethodUtils { @NotNull SamConversionResolver samResolver, @NotNull SamConversionOracle samConversionOracle ) { - TypeParameters typeParameters; + SamConstructorTypeParameters typeParameters; if (adapter instanceof SamAdapterClassConstructorDescriptor) { - typeParameters = new TypeParameters(original.getTypeParameters(), TypeSubstitutor.EMPTY); + typeParameters = new SamConstructorTypeParameters(original.getTypeParameters(), TypeSubstitutor.EMPTY); } else { - typeParameters = recreateAndInitializeTypeParameters(original.getTypeParameters(), adapter); + typeParameters = SamConstructorUtilsKt.recreateAndInitializeTypeParameters(original.getTypeParameters(), adapter); } KotlinType returnTypeUnsubstituted = original.getReturnType(); assert returnTypeUnsubstituted != null : "Creating SAM adapter for not initialized original: " + original; - TypeSubstitutor substitutor = typeParameters.substitutor; + TypeSubstitutor substitutor = typeParameters.getSubstitutor(); KotlinType returnType = substitutor.substitute(returnTypeUnsubstituted, Variance.INVARIANT); assert returnType != null : "couldn't substitute type: " + returnTypeUnsubstituted + ", substitutor = " + substitutor; @@ -214,7 +133,7 @@ public class JavaSingleAbstractMethodUtils { List valueParameters = createValueParametersForSamAdapter(original, adapter, substitutor, samResolver, samConversionOracle); - initializer.initialize(typeParameters.descriptors, valueParameters, returnType); + initializer.initialize(typeParameters.getDescriptors(), valueParameters, returnType); return adapter; } @@ -248,41 +167,6 @@ public class JavaSingleAbstractMethodUtils { return valueParameters; } - @NotNull - private static TypeParameters recreateAndInitializeTypeParameters( - @NotNull List originalParameters, - @Nullable DeclarationDescriptor newOwner - ) { - Map traitToFunTypeParameters = - JavaResolverUtils.recreateTypeParametersAndReturnMapping(originalParameters, newOwner); - TypeSubstitutor typeParametersSubstitutor = JavaResolverUtils.createSubstitutorForTypeParameters(traitToFunTypeParameters); - for (Map.Entry mapEntry : traitToFunTypeParameters.entrySet()) { - TypeParameterDescriptor traitTypeParameter = mapEntry.getKey(); - TypeParameterDescriptorImpl funTypeParameter = mapEntry.getValue(); - - for (KotlinType upperBound : traitTypeParameter.getUpperBounds()) { - KotlinType upperBoundSubstituted = typeParametersSubstitutor.substitute(upperBound, Variance.INVARIANT); - assert upperBoundSubstituted != null : "couldn't substitute type: " + upperBound + ", substitutor = " + typeParametersSubstitutor; - funTypeParameter.addUpperBound(upperBoundSubstituted); - } - - funTypeParameter.setInitialized(); - } - - List typeParameters = new ArrayList<>(traitToFunTypeParameters.values()); - return new TypeParameters(typeParameters, typeParametersSubstitutor); - } - - private static class TypeParameters { - public final List descriptors; - public final TypeSubstitutor substitutor; - - private TypeParameters(List descriptors, TypeSubstitutor substitutor) { - this.descriptors = descriptors; - this.substitutor = substitutor; - } - } - private static abstract class FunctionInitializer { public abstract void initialize( @NotNull List typeParameters, @@ -290,6 +174,4 @@ public class JavaSingleAbstractMethodUtils { @NotNull KotlinType returnType ); } - - } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/SamAdapterFunctionsScope.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/SamAdapterFunctionsScope.kt index a6b67333341..4be6ee76dc1 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/SamAdapterFunctionsScope.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/SamAdapterFunctionsScope.kt @@ -31,14 +31,11 @@ import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor 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.resolve.sam.SamConstructorDescriptor import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.calls.components.isVararg import org.jetbrains.kotlin.resolve.calls.inference.wrapWithCapturingSubstitution import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver -import org.jetbrains.kotlin.resolve.sam.SAM_LOOKUP_NAME -import org.jetbrains.kotlin.resolve.sam.SamConversionOracle -import org.jetbrains.kotlin.resolve.sam.SamConversionResolver +import org.jetbrains.kotlin.resolve.sam.* import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.ResolutionScope import org.jetbrains.kotlin.resolve.scopes.SyntheticScope @@ -75,8 +72,7 @@ class SamAdapterFunctionsScope( private val samConstructorForClassifier = storageManager.createMemoizedFunction { classifier -> - JavaSingleAbstractMethodUtils - .createSamConstructorFunction(classifier.containingDeclaration, classifier, samResolver, samConversionOracle) + createSamConstructorFunction(classifier.containingDeclaration, classifier, samResolver, samConversionOracle) } private val samConstructorForJavaConstructor = @@ -271,7 +267,7 @@ class SamAdapterFunctionsScope( val classDescriptor = classifier.classDescriptor ?: return null if (!JavaSingleAbstractMethodUtils.isSamClassDescriptor(classDescriptor)) return null - return JavaSingleAbstractMethodUtils.createTypeAliasSamConstructorFunction( + return createTypeAliasSamConstructorFunction( classifier, samConstructorForClassifier(classDescriptor), samResolver, samConversionOracle ) } diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/sam/samConstructorUtils.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/sam/samConstructorUtils.kt new file mode 100644 index 00000000000..4ec79cc195f --- /dev/null +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/sam/samConstructorUtils.kt @@ -0,0 +1,158 @@ +/* + * 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.resolve.sam + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.annotations.Annotations.Companion.EMPTY +import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl +import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl +import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.types.typeUtil.asTypeProjection +import java.util.* + +fun createSamConstructorFunction( + owner: DeclarationDescriptor, + samInterface: ClassDescriptor, + samResolver: SamConversionResolver, + samConversionOracle: SamConversionOracle +): SamConstructorDescriptor { + assert(getSingleAbstractMethodOrNull(samInterface) != null) { samInterface } + + val result = SamConstructorDescriptorImpl(owner, samInterface) + val samTypeParameters = samInterface.typeConstructor.parameters + val unsubstitutedSamType = samInterface.defaultType + + initializeSamConstructorDescriptor( + samInterface, + result, + samTypeParameters, + unsubstitutedSamType, + samResolver, + samConversionOracle + ) + + return result +} + +fun createTypeAliasSamConstructorFunction( + typeAliasDescriptor: TypeAliasDescriptor, + underlyingSamConstructor: SamConstructorDescriptor, + samResolver: SamConversionResolver, + samConversionOracle: SamConversionOracle +): SamConstructorDescriptor? { + val result = SamTypeAliasConstructorDescriptorImpl(typeAliasDescriptor, underlyingSamConstructor) + val samInterface = underlyingSamConstructor.baseDescriptorForSynthetic + val samTypeParameters = typeAliasDescriptor.typeConstructor.parameters + val unsubstitutedSamType = typeAliasDescriptor.expandedType + + initializeSamConstructorDescriptor( + samInterface, + result, + samTypeParameters, + unsubstitutedSamType, + samResolver, + samConversionOracle + ) + + return result +} + +private fun initializeSamConstructorDescriptor( + samInterface: ClassDescriptor, + samConstructor: SimpleFunctionDescriptorImpl, + samTypeParameters: List, + unsubstitutedSamType: KotlinType, + samResolver: SamConversionResolver, + samConversionOracle: SamConversionOracle +) { + val typeParameters = recreateAndInitializeTypeParameters(samTypeParameters, samConstructor) + val parameterTypeUnsubstituted = getFunctionTypeForSamType(unsubstitutedSamType, samResolver, samConversionOracle) + ?: error("couldn't get function type for SAM type $unsubstitutedSamType") + + val parameterType = + typeParameters.substitutor.substitute(parameterTypeUnsubstituted, Variance.IN_VARIANCE) ?: error( + "couldn't substitute type: " + parameterTypeUnsubstituted + + ", substitutor = " + typeParameters.substitutor + ) + + val parameter = ValueParameterDescriptorImpl( + samConstructor, null, 0, EMPTY, Name.identifier("function"), + parameterType, + declaresDefaultValue = false, + isCrossinline = false, + isNoinline = false, + varargElementType = null, + source = SourceElement.NO_SOURCE + ) + + val returnType = + typeParameters.substitutor.substitute(unsubstitutedSamType, Variance.OUT_VARIANCE) ?: error( + "couldn't substitute type: " + unsubstitutedSamType + + ", substitutor = " + typeParameters.substitutor + ) + + samConstructor.initialize( + null, + null, + typeParameters.descriptors, listOf(parameter), + returnType, + Modality.FINAL, + samInterface.visibility + ) +} + +fun recreateAndInitializeTypeParameters( + originalParameters: List, + newOwner: DeclarationDescriptor? +): SamConstructorTypeParameters { + val interfaceToFunTypeParameters = recreateTypeParametersAndReturnMapping(originalParameters, newOwner) + + val typeParametersSubstitutor = createSubstitutorForTypeParameters(interfaceToFunTypeParameters) + + for ((interfaceTypeParameter, funTypeParameter) in interfaceToFunTypeParameters) { + for (upperBound in interfaceTypeParameter.upperBounds) { + val upperBoundSubstituted = + typeParametersSubstitutor.substitute(upperBound, Variance.INVARIANT) + ?: error("couldn't substitute type: $upperBound, substitutor = $typeParametersSubstitutor") + funTypeParameter.addUpperBound(upperBoundSubstituted) + } + funTypeParameter.setInitialized() + } + return SamConstructorTypeParameters(interfaceToFunTypeParameters.values.toList(), typeParametersSubstitutor) +} + +fun recreateTypeParametersAndReturnMapping( + originalParameters: List, + newOwner: DeclarationDescriptor? +): Map = + originalParameters.associateWith { typeParameter -> + TypeParameterDescriptorImpl.createForFurtherModification( + newOwner ?: typeParameter.containingDeclaration, + typeParameter.annotations, + typeParameter.isReified, + typeParameter.variance, + typeParameter.name, + typeParameter.index, + SourceElement.NO_SOURCE, + typeParameter.storageManager + ) + } + +fun createSubstitutorForTypeParameters( + originalToAltTypeParameters: Map +): TypeSubstitutor { + val typeSubstitutionContext = + originalToAltTypeParameters + .map { (key, value) -> key.typeConstructor to value.defaultType.asTypeProjection() } + .toMap() + + // TODO: Use IndexedParametersSubstitution here instead of map creation + return TypeSubstitutor.create(typeSubstitutionContext) +} + +class SamConstructorTypeParameters(val descriptors: List, val substitutor: TypeSubstitutor) \ No newline at end of file