diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/JavaBasedSamConversionResolver.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/JavaBasedSamConversionResolver.kt index efd4aea0a0f..93935cb6f7c 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/JavaBasedSamConversionResolver.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/JavaBasedSamConversionResolver.kt @@ -5,9 +5,16 @@ package org.jetbrains.kotlin.load.java.sam +import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor +import org.jetbrains.kotlin.load.java.descriptors.JavaClassConstructorDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor +import org.jetbrains.kotlin.resolve.sam.SamConversionOracle import org.jetbrains.kotlin.resolve.sam.SamConversionResolver +import org.jetbrains.kotlin.synthetic.hasJavaOriginInHierarchy +import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.SimpleType object JavaBasedSamConversionResolver : SamConversionResolver { @@ -15,4 +22,20 @@ object JavaBasedSamConversionResolver : SamConversionResolver { if (classDescriptor !is JavaClassDescriptor) return null return classDescriptor.defaultFunctionTypeForSamInterface } +} + +object JavaBasedSamConversionOracle : SamConversionOracle { + override fun shouldRunSamConversionForFunction(candidate: CallableDescriptor): Boolean { + val functionDescriptor = candidate.original as? FunctionDescriptor ?: return false + if (functionDescriptor is TypeAliasConstructorDescriptor && + functionDescriptor.underlyingConstructorDescriptor is JavaClassConstructorDescriptor + ) return true + + return functionDescriptor.hasJavaOriginInHierarchy() + } + + override fun isPossibleSamType(samType: KotlinType): Boolean { + val descriptor = samType.constructor.declarationDescriptor + return descriptor is ClassDescriptor && (descriptor.isFun || descriptor is JavaClassDescriptor) + } } \ No newline at end of file diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/JvmSamConversionOracle.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/JvmSamConversionOracle.kt index 87ed4afce00..a1072a43e6a 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/JvmSamConversionOracle.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/JvmSamConversionOracle.kt @@ -8,13 +8,7 @@ package org.jetbrains.kotlin.load.java.sam import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.CallableDescriptor -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor -import org.jetbrains.kotlin.load.java.descriptors.JavaClassConstructorDescriptor -import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor import org.jetbrains.kotlin.resolve.sam.SamConversionOracle -import org.jetbrains.kotlin.synthetic.hasJavaOriginInHierarchy import org.jetbrains.kotlin.types.KotlinType class JvmSamConversionOracle( @@ -23,16 +17,9 @@ class JvmSamConversionOracle( override fun shouldRunSamConversionForFunction(candidate: CallableDescriptor): Boolean { if (languageVersionSettings.supportsFeature(LanguageFeature.SamConversionForKotlinFunctions)) return true - - val functionDescriptor = candidate.original as? FunctionDescriptor ?: return false - if (functionDescriptor is TypeAliasConstructorDescriptor && - functionDescriptor.underlyingConstructorDescriptor is JavaClassConstructorDescriptor) return true - - return functionDescriptor.hasJavaOriginInHierarchy() + return JavaBasedSamConversionOracle.shouldRunSamConversionForFunction(candidate) } - override fun isPossibleSamType(samType: KotlinType): Boolean { - val descriptor = samType.constructor.declarationDescriptor - return descriptor is ClassDescriptor && (descriptor.isFun || descriptor is JavaClassDescriptor) - } + override fun isPossibleSamType(samType: KotlinType): Boolean = + JavaBasedSamConversionOracle.isPossibleSamType(samType) } \ No newline at end of file diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SingleAbstractMethodUtils.java b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SingleAbstractMethodUtils.java index 5ea78c954d3..651582498da 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SingleAbstractMethodUtils.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SingleAbstractMethodUtils.java @@ -24,77 +24,33 @@ 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.JavaClassDescriptor; 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.sam.SamConversionResolver; import org.jetbrains.kotlin.resolve.jvm.JavaResolverUtils; +import org.jetbrains.kotlin.resolve.sam.SamConversionOracle; +import org.jetbrains.kotlin.resolve.sam.SamConversionResolver; import org.jetbrains.kotlin.resolve.sam.SamConversionResolverImplKt; -import org.jetbrains.kotlin.types.*; +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; -import static org.jetbrains.kotlin.resolve.sam.SamConversionResolverImplKt.nonProjectionParametrization; -import static org.jetbrains.kotlin.types.Variance.IN_VARIANCE; - public class SingleAbstractMethodUtils { private SingleAbstractMethodUtils() { } - @Nullable - public static KotlinType getFunctionTypeForSamType(@NotNull KotlinType samType, @NotNull SamConversionResolver samResolver) { - UnwrappedType unwrappedType = samType.unwrap(); - if (unwrappedType instanceof FlexibleType) { - SimpleType lower = getFunctionTypeForSamType(((FlexibleType) unwrappedType).getLowerBound(), samResolver); - SimpleType upper = getFunctionTypeForSamType(((FlexibleType) unwrappedType).getUpperBound(), samResolver); - assert (lower == null) == (upper == null) : "Illegal flexible type: " + unwrappedType; - - if (upper == null) return null; - return KotlinTypeFactory.flexibleType(lower, upper); - } - else { - return getFunctionTypeForSamType((SimpleType) unwrappedType, samResolver); - } - } - - @Nullable - private static SimpleType getFunctionTypeForSamType(@NotNull SimpleType samType, @NotNull SamConversionResolver samResolver) { - // e.g. samType == Comparator? - - ClassifierDescriptor classifier = samType.getConstructor().getDeclarationDescriptor(); - if (classifier instanceof ClassDescriptor) { - ClassDescriptor descriptor = (ClassDescriptor) classifier; - if (!(descriptor instanceof JavaClassDescriptor) && !descriptor.isFun()) return null; - - // Function2 - SimpleType functionTypeDefault = samResolver.resolveFunctionTypeIfSamInterface(descriptor); - - if (functionTypeDefault != null) { - SimpleType noProjectionsSamType = nonProjectionParametrization(samType); - if (noProjectionsSamType == null) return null; - - // Function2? - KotlinType type = TypeSubstitutor.create(noProjectionsSamType).substitute(functionTypeDefault, IN_VARIANCE); - assert type != null : "Substitution based on type with no projections '" + noProjectionsSamType + - "' should not end with conflict"; - - SimpleType simpleType = TypeSubstitutionKt.asSimpleType(type); - - return simpleType.makeNullableAsSpecified(samType.isMarkedNullable()); - } - } - return null; - } - @NotNull public static SamConstructorDescriptor createSamConstructorFunction( @NotNull DeclarationDescriptor owner, @NotNull ClassDescriptor samInterface, - @NotNull SamConversionResolver samResolver + @NotNull SamConversionResolver samResolver, + @NotNull SamConversionOracle samConversionOracle ) { assert SamConversionResolverImplKt.getSingleAbstractMethodOrNull(samInterface) != null : samInterface; @@ -102,7 +58,7 @@ public class SingleAbstractMethodUtils { List samTypeParameters = samInterface.getTypeConstructor().getParameters(); SimpleType unsubstitutedSamType = samInterface.getDefaultType(); - initializeSamConstructorDescriptor(samInterface, result, samTypeParameters, unsubstitutedSamType, samResolver); + initializeSamConstructorDescriptor(samInterface, result, samTypeParameters, unsubstitutedSamType, samResolver, samConversionOracle); return result; } @@ -112,11 +68,13 @@ public class SingleAbstractMethodUtils { @NotNull SimpleFunctionDescriptorImpl samConstructor, @NotNull List samTypeParameters, @NotNull KotlinType unsubstitutedSamType, - @NotNull SamConversionResolver samResolver + @NotNull SamConversionResolver samResolver, + @NotNull SamConversionOracle samConversionOracle ) { TypeParameters typeParameters = recreateAndInitializeTypeParameters(samTypeParameters, samConstructor); - KotlinType parameterTypeUnsubstituted = getFunctionTypeForSamType(unsubstitutedSamType, samResolver); + 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 + @@ -146,14 +104,15 @@ public class SingleAbstractMethodUtils { public static SamConstructorDescriptor createTypeAliasSamConstructorFunction( @NotNull TypeAliasDescriptor typeAliasDescriptor, @NotNull SamConstructorDescriptor underlyingSamConstructor, - @NotNull SamConversionResolver samResolver + @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); + initializeSamConstructorDescriptor(samInterface, result, samTypeParameters, unsubstitutedSamType, samResolver, samConversionOracle); return result; } @@ -169,7 +128,9 @@ public class SingleAbstractMethodUtils { ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor(); if (descriptor instanceof ClassDescriptor && ((ClassDescriptor) descriptor).isFun()) return true; - return getFunctionTypeForSamType(type, JavaBasedSamConversionResolver.INSTANCE) != null; + return SamConversionResolverImplKt.getFunctionTypeForSamType( + type, JavaBasedSamConversionResolver.INSTANCE, JavaBasedSamConversionOracle.INSTANCE + ) != null; } public static boolean isSamAdapterNecessary(@NotNull FunctionDescriptor fun) { @@ -184,7 +145,8 @@ public class SingleAbstractMethodUtils { @NotNull public static SamAdapterDescriptor createSamAdapterFunction( @NotNull JavaMethodDescriptor original, - @NotNull SamConversionResolver samResolver + @NotNull SamConversionResolver samResolver, + @NotNull SamConversionOracle samConversionOracle ) { SamAdapterFunctionDescriptor result = new SamAdapterFunctionDescriptor(original); return initSamAdapter(original, result, new FunctionInitializer() { @@ -204,13 +166,14 @@ public class SingleAbstractMethodUtils { original.getVisibility() ); } - }, samResolver); + }, samResolver, samConversionOracle); } @NotNull public static SamAdapterDescriptor createSamAdapterConstructor( @NotNull JavaClassConstructorDescriptor original, - @NotNull SamConversionResolver samResolver + @NotNull SamConversionResolver samResolver, + @NotNull SamConversionOracle samConversionOracle ) { SamAdapterClassConstructorDescriptor result = new SamAdapterClassConstructorDescriptor(original); return initSamAdapter(original, result, new FunctionInitializer() { @@ -223,7 +186,7 @@ public class SingleAbstractMethodUtils { result.initialize(valueParameters, original.getVisibility()); result.setReturnType(returnType); } - }, samResolver); + }, samResolver, samConversionOracle); } @NotNull @@ -231,7 +194,8 @@ public class SingleAbstractMethodUtils { @NotNull F original, @NotNull SamAdapterDescriptor adapter, @NotNull FunctionInitializer initializer, - @NotNull SamConversionResolver samResolver + @NotNull SamConversionResolver samResolver, + @NotNull SamConversionOracle samConversionOracle ) { TypeParameters typeParameters = recreateAndInitializeTypeParameters(original.getTypeParameters(), adapter); @@ -244,7 +208,8 @@ public class SingleAbstractMethodUtils { ", substitutor = " + substitutor; - List valueParameters = createValueParametersForSamAdapter(original, adapter, substitutor, samResolver); + List valueParameters = + createValueParametersForSamAdapter(original, adapter, substitutor, samResolver, samConversionOracle); initializer.initialize(typeParameters.descriptors, valueParameters, returnType); @@ -255,13 +220,14 @@ public class SingleAbstractMethodUtils { @NotNull FunctionDescriptor original, @NotNull FunctionDescriptor samAdapter, @NotNull TypeSubstitutor substitutor, - @NotNull SamConversionResolver samResolver + @NotNull SamConversionResolver samResolver, + @NotNull SamConversionOracle samConversionOracle ) { List originalValueParameters = original.getValueParameters(); List valueParameters = new ArrayList<>(originalValueParameters.size()); for (ValueParameterDescriptor originalParam : originalValueParameters) { KotlinType originalType = originalParam.getType(); - KotlinType functionType = getFunctionTypeForSamType(originalType, samResolver); + KotlinType functionType = SamConversionResolverImplKt.getFunctionTypeForSamType(originalType, samResolver, samConversionOracle); KotlinType newTypeUnsubstituted = functionType != null ? functionType : originalType; KotlinType newType = substitutor.substitute(newTypeUnsubstituted, Variance.IN_VARIANCE); assert newType != null : "couldn't substitute type: " + newTypeUnsubstituted + ", substitutor = " + substitutor; diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/JavaSyntheticScopes.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/JavaSyntheticScopes.kt index f66ea3ba486..347e8edc48b 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/JavaSyntheticScopes.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/JavaSyntheticScopes.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.resolve.sam.SamConversionResolver import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver +import org.jetbrains.kotlin.resolve.sam.SamConversionOracle import org.jetbrains.kotlin.resolve.scopes.SyntheticScope import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes import org.jetbrains.kotlin.storage.StorageManager @@ -35,6 +36,7 @@ class JavaSyntheticScopes( lookupTracker: LookupTracker, languageVersionSettings: LanguageVersionSettings, samConventionResolver: SamConversionResolver, + samConversionOracle: SamConversionOracle, deprecationResolver: DeprecationResolver ) : SyntheticScopes { override val scopes: Collection @@ -57,6 +59,7 @@ class JavaSyntheticScopes( val samAdapterFunctionsScope = SamAdapterFunctionsScope( storageManager, samConventionResolver, + samConversionOracle, deprecationResolver, lookupTracker, samViaSyntheticScopeDisabled = samConversionPerArgumentIsEnabled, @@ -71,6 +74,7 @@ class JavaSyntheticScopes( val forceEnabledSamAdapterFunctionsScope = SamAdapterFunctionsScope( storageManager, samConventionResolver, + samConversionOracle, deprecationResolver, lookupTracker, samViaSyntheticScopeDisabled = false, 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 a7d411270f2..aaee5295759 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/SamAdapterFunctionsScope.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/SamAdapterFunctionsScope.kt @@ -37,6 +37,7 @@ 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.SamConversionOracle import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.ResolutionScope import org.jetbrains.kotlin.resolve.scopes.SyntheticScope @@ -54,6 +55,7 @@ val SAM_LOOKUP_NAME = Name.special("") class SamAdapterFunctionsScope( storageManager: StorageManager, private val samResolver: SamConversionResolver, + private val samConversionOracle: SamConversionOracle, private val deprecationResolver: DeprecationResolver, private val lookupTracker: LookupTracker, private val samViaSyntheticScopeDisabled: Boolean, @@ -68,17 +70,17 @@ class SamAdapterFunctionsScope( private val samAdapterForStaticFunction = storageManager.createMemoizedFunction> { function -> - SingleAbstractMethodUtils.createSamAdapterFunction(function, samResolver) + SingleAbstractMethodUtils.createSamAdapterFunction(function, samResolver, samConversionOracle) } private val samConstructorForClassifier = storageManager.createMemoizedFunction { classifier -> - SingleAbstractMethodUtils.createSamConstructorFunction(classifier.containingDeclaration, classifier, samResolver) + SingleAbstractMethodUtils.createSamConstructorFunction(classifier.containingDeclaration, classifier, samResolver, samConversionOracle) } private val samConstructorForJavaConstructor = storageManager.createMemoizedFunction { constructor -> - SingleAbstractMethodUtils.createSamAdapterConstructor(constructor, samResolver) as ClassConstructorDescriptor + SingleAbstractMethodUtils.createSamAdapterConstructor(constructor, samResolver, samConversionOracle) as ClassConstructorDescriptor } private val samConstructorForTypeAliasConstructor = @@ -93,7 +95,7 @@ class SamAdapterFunctionsScope( if (!SingleAbstractMethodUtils.isSamAdapterNecessary(function)) return null if (function.returnType == null) return null if (deprecationResolver.isHiddenInResolution(function)) return null - return SamAdapterExtensionFunctionDescriptorImpl.create(function, samResolver) + return SamAdapterExtensionFunctionDescriptorImpl.create(function, samResolver, samConversionOracle) } override fun getSyntheticMemberFunctions( @@ -269,7 +271,8 @@ class SamAdapterFunctionsScope( if (!SingleAbstractMethodUtils.isSamClassDescriptor(classDescriptor)) return null return SingleAbstractMethodUtils.createTypeAliasSamConstructorFunction( - classifier, samConstructorForClassifier(classDescriptor), samResolver) + classifier, samConstructorForClassifier(classDescriptor), samResolver, samConversionOracle + ) } private class SamAdapterExtensionFunctionDescriptorImpl( @@ -289,7 +292,11 @@ class SamAdapterFunctionsScope( } companion object { - fun create(sourceFunction: FunctionDescriptor, samResolver: SamConversionResolver): SamAdapterExtensionFunctionDescriptorImpl { + fun create( + sourceFunction: FunctionDescriptor, + samResolver: SamConversionResolver, + samConversionOracle: SamConversionOracle + ): SamAdapterExtensionFunctionDescriptorImpl { val descriptor = SamAdapterExtensionFunctionDescriptorImpl( sourceFunction.containingDeclaration, null, @@ -307,7 +314,8 @@ class SamAdapterFunctionsScope( val returnType = typeSubstitutor.safeSubstitute(sourceFunction.returnType!!, Variance.INVARIANT) val valueParameters = SingleAbstractMethodUtils.createValueParametersForSamAdapter( - sourceFunction, descriptor, typeSubstitutor, samResolver) + sourceFunction, descriptor, typeSubstitutor, samResolver, samConversionOracle + ) val visibility = syntheticVisibility(sourceFunction, isUsedForExtension = false) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt index 0e799d1bd90..b0655211bdb 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt @@ -312,7 +312,10 @@ private fun KotlinResolutionCandidate.getExpectedTypeWithSAMConversion( !callComponents.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitVarargAsArrayAfterSamArgument) if (generatingAdditionalSamCandidateIsEnabled) return null - if (!callComponents.samConversionOracle.shouldRunSamConversionForFunction(resolvedCall.candidateDescriptor)) return null + val samConversionOracle = callComponents.samConversionOracle + if (!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.SamConversionForKotlinFunctions)) { + if (!samConversionOracle.shouldRunSamConversionForFunction(resolvedCall.candidateDescriptor)) return null + } val argumentIsFunctional = when (argument) { is SimpleKotlinCallArgument -> argument.receiver.stableType.isFunctionType @@ -323,13 +326,12 @@ private fun KotlinResolutionCandidate.getExpectedTypeWithSAMConversion( val originalExpectedType = argument.getExpectedType(candidateParameter.original, callComponents.languageVersionSettings) - if (!callComponents.samConversionOracle.isPossibleSamType(originalExpectedType)) return null - val convertedTypeByOriginal = - callComponents.samConversionResolver.getFunctionTypeForPossibleSamType(originalExpectedType) ?: return null + callComponents.samConversionResolver.getFunctionTypeForPossibleSamType(originalExpectedType, samConversionOracle) ?: return null val candidateExpectedType = argument.getExpectedType(candidateParameter, callComponents.languageVersionSettings) - val convertedTypeByCandidate = callComponents.samConversionResolver.getFunctionTypeForPossibleSamType(candidateExpectedType) + val convertedTypeByCandidate = + callComponents.samConversionResolver.getFunctionTypeForPossibleSamType(candidateExpectedType, samConversionOracle) assert(candidateExpectedType.constructor == originalExpectedType.constructor && convertedTypeByCandidate != null) { "If original type is SAM type, then candidate should have same type constructor and corresponding function type\n" + diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/sam/SamConversionResolverImpl.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/sam/SamConversionResolverImpl.kt index fa42e4d50f4..dc7c7525204 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/sam/SamConversionResolverImpl.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/sam/SamConversionResolverImpl.kt @@ -95,14 +95,20 @@ fun getFunctionTypeForAbstractMethod( ) } -fun SamConversionResolver.getFunctionTypeForPossibleSamType(possibleSamType: UnwrappedType): UnwrappedType? = - getFunctionTypeForSamType(possibleSamType, this)?.unwrap() +fun SamConversionResolver.getFunctionTypeForPossibleSamType( + possibleSamType: UnwrappedType, + samConversionOracle: SamConversionOracle +): UnwrappedType? = getFunctionTypeForSamType(possibleSamType, this, samConversionOracle)?.unwrap() -fun getFunctionTypeForSamType(samType: KotlinType, samResolver: SamConversionResolver): KotlinType? { +fun getFunctionTypeForSamType( + samType: KotlinType, + samResolver: SamConversionResolver, + samConversionOracle: SamConversionOracle +): KotlinType? { val unwrappedType = samType.unwrap() if (unwrappedType is FlexibleType) { - val lower = getFunctionTypeForSamType(unwrappedType.lowerBound, samResolver) - val upper = getFunctionTypeForSamType(unwrappedType.upperBound, samResolver) + val lower = getFunctionTypeForSamType(unwrappedType.lowerBound, samResolver, samConversionOracle) + val upper = getFunctionTypeForSamType(unwrappedType.upperBound, samResolver, samConversionOracle) assert((lower == null) == (upper == null)) { "Illegal flexible type: $unwrappedType" } @@ -110,15 +116,21 @@ fun getFunctionTypeForSamType(samType: KotlinType, samResolver: SamConversionRes return KotlinTypeFactory.flexibleType(lower, upper) } else { - return getFunctionTypeForSamType(unwrappedType as SimpleType, samResolver) + return getFunctionTypeForSamType(unwrappedType as SimpleType, samResolver, samConversionOracle) } } -private fun getFunctionTypeForSamType(samType: SimpleType, samResolver: SamConversionResolver): SimpleType? { +private fun getFunctionTypeForSamType( + samType: SimpleType, + samResolver: SamConversionResolver, + samConversionOracle: SamConversionOracle +): SimpleType? { // e.g. samType == Comparator? val classifier = samType.constructor.declarationDescriptor if (classifier !is ClassDescriptor) return null + if (!samConversionOracle.isPossibleSamType(samType)) return null + // Function2 val functionTypeDefault = samResolver.resolveFunctionTypeIfSamInterface(classifier) ?: return null val noProjectionsSamType = nonProjectionParametrization(samType) ?: return null diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/psiModificationUtils.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/psiModificationUtils.kt index 46fdbe25983..3d290d3f17d 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/psiModificationUtils.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/psiModificationUtils.kt @@ -36,6 +36,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.callUtil.getValueArgumentsInParentheses import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode +import org.jetbrains.kotlin.resolve.sam.SamConversionOracle import org.jetbrains.kotlin.resolve.sam.SamConversionResolver import org.jetbrains.kotlin.resolve.sam.getFunctionTypeForPossibleSamType import org.jetbrains.kotlin.types.KotlinType @@ -129,6 +130,7 @@ fun KtCallExpression.canMoveLambdaOutsideParentheses(): Boolean { val resolutionFacade = getResolutionFacade() val samConversionTransformer = resolutionFacade.frontendService() + val samConversionOracle = resolutionFacade.frontendService() val languageVersionSettings = resolutionFacade.frontendService() val bindingContext = analyze(resolutionFacade, BodyResolveMode.PARTIAL) @@ -143,6 +145,7 @@ fun KtCallExpression.canMoveLambdaOutsideParentheses(): Boolean { it.allowsMoveOfLastParameterOutsideParentheses( lambdaArgumentCount + referenceArgumentCount, samConversionTransformer, + samConversionOracle, languageVersionSettings.supportsFeature(LanguageFeature.NewInference) ) } @@ -156,6 +159,7 @@ fun KtCallExpression.canMoveLambdaOutsideParentheses(): Boolean { private fun FunctionDescriptor.allowsMoveOfLastParameterOutsideParentheses( lambdaAndCallableReferencesInOriginalCallCount: Int, samConversionTransformer: SamConversionResolver, + samConversionOracle: SamConversionOracle, newInferenceEnabled: Boolean ): Boolean { fun KotlinType.allowsMoveOutsideParentheses(): Boolean { @@ -167,7 +171,7 @@ private fun FunctionDescriptor.allowsMoveOfLastParameterOutsideParentheses( // converted types, but in NI it is performed by conversions, so we check it explicitly // Also note that 'newInferenceEnabled' is essentially a micro-optimization, as there are no // harm in just calling 'samConversionTransformer' on all candidates. - return newInferenceEnabled && samConversionTransformer.getFunctionTypeForPossibleSamType(this.unwrap()) != null + return newInferenceEnabled && samConversionTransformer.getFunctionTypeForPossibleSamType(this.unwrap(), samConversionOracle) != null } val params = valueParameters