diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/samConversionUtils.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/samConversionUtils.kt index 84c265e4630..3cf482e2bff 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/samConversionUtils.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/samConversionUtils.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.resolve.calls.components import org.jetbrains.kotlin.builtins.isFunctionType +import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ParameterDescriptor @@ -16,21 +17,46 @@ import org.jetbrains.kotlin.resolve.sam.getFunctionTypeForPossibleSamType import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.typeUtil.isNothing +object SamTypeConversions { + fun conversionMightBeNeededBeforeSubtypingCheck(argument: KotlinCallArgument): Boolean { + return when (argument) { + is SimpleKotlinCallArgument -> argument.receiver.stableType.isFunctionType + is LambdaKotlinCallArgument, is CallableReferenceKotlinCallArgument -> true + else -> false + } + } + + fun conversionMightBeNeededAfterSubtypingCheck(argument: KotlinCallArgument): Boolean { + return argument is SimpleKotlinCallArgument && argument.receiver.stableType.isFunctionTypeOrSubtype + } + + + fun conversionDefinitelyNotNeeded( + candidate: KotlinResolutionCandidate, + candidateParameter: ParameterDescriptor + ): Boolean { + val callComponents = candidate.callComponents + val generatingAdditionalSamCandidateIsEnabled = + !callComponents.languageVersionSettings.supportsFeature(LanguageFeature.SamConversionPerArgument) && + !callComponents.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitVarargAsArrayAfterSamArgument) + + if (generatingAdditionalSamCandidateIsEnabled) return true + if (candidateParameter.type.isNothing()) return true + + val samConversionOracle = callComponents.samConversionOracle + if (!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.SamConversionForKotlinFunctions)) { + if (!samConversionOracle.shouldRunSamConversionForFunction(candidate.resolvedCall.candidateDescriptor)) return true + } + + return false + } +} + fun KotlinResolutionCandidate.getExpectedTypeWithSAMConversion( argument: KotlinCallArgument, candidateParameter: ParameterDescriptor ): UnwrappedType? { - val generatingAdditionalSamCandidateIsEnabled = - !callComponents.languageVersionSettings.supportsFeature(LanguageFeature.SamConversionPerArgument) && - !callComponents.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitVarargAsArrayAfterSamArgument) - - if (generatingAdditionalSamCandidateIsEnabled) return null - if (candidateParameter.type.isNothing()) return null - - val samConversionOracle = callComponents.samConversionOracle - if (!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.SamConversionForKotlinFunctions)) { - if (!samConversionOracle.shouldRunSamConversionForFunction(resolvedCall.candidateDescriptor)) return null - } + if (SamTypeConversions.conversionDefinitelyNotNeeded(this, candidateParameter)) return null val argumentIsFunctional = when (argument) { is SimpleKotlinCallArgument -> argument.receiver.stableType.isFunctionType @@ -42,11 +68,17 @@ fun KotlinResolutionCandidate.getExpectedTypeWithSAMConversion( val originalExpectedType = argument.getExpectedType(candidateParameter.original, callComponents.languageVersionSettings) val convertedTypeByOriginal = - callComponents.samConversionResolver.getFunctionTypeForPossibleSamType(originalExpectedType, samConversionOracle) ?: return null + callComponents.samConversionResolver.getFunctionTypeForPossibleSamType( + originalExpectedType, + callComponents.samConversionOracle + ) ?: return null val candidateExpectedType = argument.getExpectedType(candidateParameter, callComponents.languageVersionSettings) val convertedTypeByCandidate = - callComponents.samConversionResolver.getFunctionTypeForPossibleSamType(candidateExpectedType, samConversionOracle) + callComponents.samConversionResolver.getFunctionTypeForPossibleSamType( + candidateExpectedType, + callComponents.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/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/suspendConversionUtils.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/suspendConversionUtils.kt index 525a953c69a..a53a9670f6a 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/suspendConversionUtils.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/suspendConversionUtils.kt @@ -11,21 +11,37 @@ import org.jetbrains.kotlin.descriptors.ParameterDescriptor import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.types.UnwrappedType +object SuspendTypeConversions { + fun conversionDefinitelyNotNeeded( + candidate: KotlinResolutionCandidate, + argument: KotlinCallArgument, + candidateParameter: ParameterDescriptor + ): Boolean { + if (!candidate.callComponents.languageVersionSettings.supportsFeature(LanguageFeature.SuspendConversion)) return true + + if (argument !is SimpleKotlinCallArgument) return true + + val argumentType = argument.receiver.stableType + if (!argumentType.isFunctionType) return true + if (argumentType.isSuspendFunctionType) return true + + if (!candidateParameter.type.isSuspendFunctionType) return true + + return false + } + + fun KotlinResolutionCandidate.conversionMightBeNeededBeforeSubtypingCheck(): Boolean = true + fun KotlinResolutionCandidate.conversionMightBeNeededAfterSubtypingCheck(): Boolean = false +} + + fun KotlinResolutionCandidate.getExpectedTypeWithSuspendConversion( argument: KotlinCallArgument, candidateParameter: ParameterDescriptor ): UnwrappedType? { - if (!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.SuspendConversion)) return null - - if (argument !is SimpleKotlinCallArgument) return null - - val argumentType = argument.receiver.stableType - if (!argumentType.isFunctionType) return null - if (argumentType.isSuspendFunctionType) return null + if (SuspendTypeConversions.conversionDefinitelyNotNeeded(this, argument, candidateParameter)) return null val parameterType = candidateParameter.type - if (!parameterType.isSuspendFunctionType) return null - val nonSuspendParameterType = createFunctionType( callComponents.builtIns, parameterType.annotations,