diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/JvmSamConversionTransformer.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/JvmSamConversionTransformer.kt index 3669b7b5d4c..0146f609024 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/JvmSamConversionTransformer.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/JvmSamConversionTransformer.kt @@ -8,12 +8,15 @@ 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.resolve.sam.SamConversionResolver import org.jetbrains.kotlin.load.java.descriptors.JavaClassConstructorDescriptor +import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor import org.jetbrains.kotlin.resolve.calls.components.SamConversionTransformer import org.jetbrains.kotlin.synthetic.hasJavaOriginInHierarchy +import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.UnwrappedType class JvmSamConversionTransformer( @@ -33,4 +36,9 @@ class JvmSamConversionTransformer( 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/SingleAbstractMethodUtils.java b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SingleAbstractMethodUtils.java index 643f4c353ad..5ea78c954d3 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 @@ -38,6 +38,7 @@ 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 { @@ -73,7 +74,7 @@ public class SingleAbstractMethodUtils { SimpleType functionTypeDefault = samResolver.resolveFunctionTypeIfSamInterface(descriptor); if (functionTypeDefault != null) { - SimpleType noProjectionsSamType = SingleAbstractMethodUtilsKt.nonProjectionParametrization(samType); + SimpleType noProjectionsSamType = nonProjectionParametrization(samType); if (noProjectionsSamType == null) return null; // Function2? diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SingleAbstractMethodUtils.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SingleAbstractMethodUtils.kt deleted file mode 100644 index 255e6f5bd22..00000000000 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SingleAbstractMethodUtils.kt +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.load.java.sam - -import org.jetbrains.kotlin.types.SimpleType -import org.jetbrains.kotlin.types.Variance -import org.jetbrains.kotlin.types.replace -import org.jetbrains.kotlin.types.typeUtil.asTypeProjection -import org.jetbrains.kotlin.types.typeUtil.contains - -// If type 'samType' contains no projection, then it's non-projection parametrization is 'samType' itself -// Else each projection type argument 'out/in A_i' (but star projections) is replaced with it's bound 'A_i' -// Star projections are treated specially: -// - If first upper bound of corresponding type parameter does not contain any type parameter of 'samType' class, -// then use this upper bound instead of star projection -// - Otherwise no non-projection parametrization exists for such 'samType' -// -// See Non-wildcard parametrization in JLS 8 p.9.9 for clarification -internal fun nonProjectionParametrization(samType: SimpleType): SimpleType? { - if (samType.arguments.none { it.projectionKind != Variance.INVARIANT }) return samType - val parameters = samType.constructor.parameters - val parametersSet = parameters.toSet() - - return samType.replace( - newArguments = samType.arguments.zip(parameters).map { - val (projection, parameter) = it - when { - projection.projectionKind == Variance.INVARIANT -> projection - - projection.isStarProjection -> - parameter.upperBounds.first().takeUnless { - t -> t.contains { it.constructor.declarationDescriptor in parametersSet } - }?.asTypeProjection() ?: return@nonProjectionParametrization null - - else -> projection.type.asTypeProjection() - } - }) -} diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt index cc95d191ffc..08ac18f24cf 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.container.DefaultImplementation 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.annotations.Annotations @@ -17,6 +18,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower +import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.StubType import org.jetbrains.kotlin.types.UnwrappedType @@ -80,8 +82,14 @@ interface SamConversionTransformer { fun shouldRunSamConversionForFunction(candidate: CallableDescriptor): Boolean + fun isPossibleSamType(samType: KotlinType): Boolean + object Empty : SamConversionTransformer { override fun getFunctionTypeForPossibleSamType(possibleSamType: UnwrappedType): UnwrappedType? = null override fun shouldRunSamConversionForFunction(candidate: CallableDescriptor): Boolean = false + override fun isPossibleSamType(samType: KotlinType): Boolean { + val descriptor = samType.constructor.declarationDescriptor + return descriptor is ClassDescriptor && descriptor.isFun + } } } \ No newline at end of file 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 7baf5922a1f..154ea1394a0 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 @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.* import org.jetbrains.kotlin.resolve.calls.tower.InfixCallNoInfixModifier import org.jetbrains.kotlin.resolve.calls.tower.InvokeConventionCallNoOperatorModifier import org.jetbrains.kotlin.resolve.calls.tower.VisibilityError +import org.jetbrains.kotlin.resolve.sam.getFunctionTypeForPossibleSamType import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.typeUtil.contains import org.jetbrains.kotlin.types.typeUtil.makeNotNullable @@ -311,7 +312,9 @@ private fun KotlinResolutionCandidate.getExpectedTypeWithSAMConversion( !callComponents.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitVarargAsArrayAfterSamArgument) if (generatingAdditionalSamCandidateIsEnabled) return null - if (!callComponents.samConversionTransformer.shouldRunSamConversionForFunction(resolvedCall.candidateDescriptor)) return null + if (!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.SamConversionForKotlinFunctions)) { + if (!callComponents.samConversionTransformer.shouldRunSamConversionForFunction(resolvedCall.candidateDescriptor)) return null + } val argumentIsFunctional = when (argument) { is SimpleKotlinCallArgument -> argument.receiver.stableType.isFunctionType @@ -321,11 +324,14 @@ private fun KotlinResolutionCandidate.getExpectedTypeWithSAMConversion( if (!argumentIsFunctional) return null val originalExpectedType = argument.getExpectedType(candidateParameter.original, callComponents.languageVersionSettings) + + if (!callComponents.samConversionTransformer.isPossibleSamType(originalExpectedType)) return null + val convertedTypeByOriginal = - callComponents.samConversionTransformer.getFunctionTypeForPossibleSamType(originalExpectedType) ?: return null + callComponents.samConversionResolver.getFunctionTypeForPossibleSamType(originalExpectedType) ?: return null val candidateExpectedType = argument.getExpectedType(candidateParameter, callComponents.languageVersionSettings) - val convertedTypeByCandidate = callComponents.samConversionTransformer.getFunctionTypeForPossibleSamType(candidateExpectedType) + val convertedTypeByCandidate = callComponents.samConversionResolver.getFunctionTypeForPossibleSamType(candidateExpectedType) 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/model/KotlinResolverContext.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinResolverContext.kt index f2e261645f9..2369ca75858 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinResolverContext.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinResolverContext.kt @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tower.* import org.jetbrains.kotlin.resolve.descriptorUtil.hasDynamicExtensionAnnotation +import org.jetbrains.kotlin.resolve.sam.SamConversionResolver import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.TypeSubstitutor @@ -44,6 +45,7 @@ class KotlinCallComponents( val builtIns: KotlinBuiltIns, val languageVersionSettings: LanguageVersionSettings, val samConversionTransformer: SamConversionTransformer, + val samConversionResolver: SamConversionResolver, val kotlinTypeChecker: NewKotlinTypeChecker ) diff --git a/compiler/testData/multiplatform/funInterfaces/common.kt b/compiler/testData/multiplatform/funInterfaces/common.kt new file mode 100644 index 00000000000..b3468ffd418 --- /dev/null +++ b/compiler/testData/multiplatform/funInterfaces/common.kt @@ -0,0 +1,15 @@ +// ADDITIONAL_COMPILER_ARGUMENTS: -XXLanguage:+NewInference +// ADDITIONAL_COMPILER_ARGUMENTS: -XXLanguage:+SamConversionForKotlinFunctions +// ADDITIONAL_COMPILER_ARGUMENTS: -XXLanguage:+SamConversionPerArgument + +package common + +fun interface KRunnable { + fun invoke(): String +} + +fun foo(k: KRunnable) = k.invoke() + +fun test() { + foo { "OK" } +} \ No newline at end of file diff --git a/compiler/testData/multiplatform/funInterfaces/js.kt b/compiler/testData/multiplatform/funInterfaces/js.kt new file mode 100644 index 00000000000..e4a2a18ddfa --- /dev/null +++ b/compiler/testData/multiplatform/funInterfaces/js.kt @@ -0,0 +1,15 @@ +// ADDITIONAL_COMPILER_ARGUMENTS: -XXLanguage:+NewInference +// ADDITIONAL_COMPILER_ARGUMENTS: -XXLanguage:+SamConversionForKotlinFunctions +// ADDITIONAL_COMPILER_ARGUMENTS: -XXLanguage:+SamConversionPerArgument + +package js + +fun interface KRunnable { + fun invoke(): String +} + +fun foo(k: KRunnable) = k.invoke() + +fun test() { + foo { "OK" } +} \ No newline at end of file diff --git a/compiler/testData/multiplatform/funInterfaces/jvm.kt b/compiler/testData/multiplatform/funInterfaces/jvm.kt new file mode 100644 index 00000000000..3191f7aa74a --- /dev/null +++ b/compiler/testData/multiplatform/funInterfaces/jvm.kt @@ -0,0 +1,15 @@ +// ADDITIONAL_COMPILER_ARGUMENTS: -XXLanguage:+NewInference +// ADDITIONAL_COMPILER_ARGUMENTS: -XXLanguage:+SamConversionForKotlinFunctions +// ADDITIONAL_COMPILER_ARGUMENTS: -XXLanguage:+SamConversionPerArgument + +package jvm + +fun interface KRunnable { + fun invoke(): String +} + +fun foo(k: KRunnable) = k.invoke() + +fun test() { + foo { "OK" } +} \ No newline at end of file diff --git a/compiler/testData/multiplatform/funInterfaces/output.txt b/compiler/testData/multiplatform/funInterfaces/output.txt new file mode 100644 index 00000000000..2d4637008a9 --- /dev/null +++ b/compiler/testData/multiplatform/funInterfaces/output.txt @@ -0,0 +1,41 @@ +-- Common -- +Exit code: OK +Output: +warning: ATTENTION! +This build uses unsafe internal compiler arguments: + +-XXLanguage:+NewInference +-XXLanguage:+SamConversionForKotlinFunctions +-XXLanguage:+SamConversionPerArgument + +This mode is not recommended for production use, +as no stability/compatibility guarantees are given on +compiler or generated code. Use it at your own risk! + +-- JVM -- +Exit code: OK +Output: +warning: ATTENTION! +This build uses unsafe internal compiler arguments: + +-XXLanguage:+NewInference +-XXLanguage:+SamConversionForKotlinFunctions +-XXLanguage:+SamConversionPerArgument + +This mode is not recommended for production use, +as no stability/compatibility guarantees are given on +compiler or generated code. Use it at your own risk! + +-- JS -- +Exit code: OK +Output: +warning: ATTENTION! +This build uses unsafe internal compiler arguments: + +-XXLanguage:+NewInference +-XXLanguage:+SamConversionForKotlinFunctions +-XXLanguage:+SamConversionPerArgument + +This mode is not recommended for production use, +as no stability/compatibility guarantees are given on +compiler or generated code. Use it at your own risk! diff --git a/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTestGenerated.java index 76e454e0baa..13389bede3b 100644 --- a/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTestGenerated.java @@ -53,6 +53,11 @@ public class MultiPlatformIntegrationTestGenerated extends AbstractMultiPlatform runTest("compiler/testData/multiplatform/explicitActualOnOverrideOfAbstractMethod/"); } + @TestMetadata("funInterfaces") + public void testFunInterfaces() throws Exception { + runTest("compiler/testData/multiplatform/funInterfaces/"); + } + @TestMetadata("genericDeclarations") public void testGenericDeclarations() throws Exception { runTest("compiler/testData/multiplatform/genericDeclarations/"); @@ -409,6 +414,19 @@ public class MultiPlatformIntegrationTestGenerated extends AbstractMultiPlatform } } + @TestMetadata("compiler/testData/multiplatform/funInterfaces") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class FunInterfaces extends AbstractMultiPlatformIntegrationTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInFunInterfaces() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/multiplatform/funInterfaces"), Pattern.compile("^([^\\.]+)$"), null, true); + } + } + @TestMetadata("compiler/testData/multiplatform/genericDeclarations") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/sam/SamConversionResolver.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/sam/SamConversionResolver.kt index 56b7081c47b..15cca3d37ab 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/sam/SamConversionResolver.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/sam/SamConversionResolver.kt @@ -10,7 +10,7 @@ import org.jetbrains.kotlin.container.PlatformSpecificExtension import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.types.SimpleType -@DefaultImplementation(impl = SamConversionResolver.Empty::class) +@DefaultImplementation(impl = SamConversionResolverImpl.SamConversionResolverWithoutReceiverConversion::class) interface SamConversionResolver : PlatformSpecificExtension { object Empty : SamConversionResolver { override fun resolveFunctionTypeIfSamInterface(classDescriptor: ClassDescriptor): SimpleType? = null 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 5a562f60191..fa42e4d50f4 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/sam/SamConversionResolverImpl.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/sam/SamConversionResolverImpl.kt @@ -11,19 +11,26 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations.Companion.EMPTY import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.sam.SamConversionResolver import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe -import org.jetbrains.kotlin.resolve.sam.SamWithReceiverResolver import org.jetbrains.kotlin.storage.StorageManager -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.SimpleType +import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.types.typeUtil.asTypeProjection +import org.jetbrains.kotlin.types.typeUtil.contains import java.util.* class SamConversionResolverImpl( - storageManager: StorageManager, - private val samWithReceiverResolvers: Iterable -): SamConversionResolver { + storageManager: StorageManager, + private val samWithReceiverResolvers: Iterable +) : SamConversionResolver { + class SamConversionResolverWithoutReceiverConversion(storageManager: StorageManager) : SamConversionResolver { + val resolver = SamConversionResolverImpl(storageManager, emptyList()) + + override fun resolveFunctionTypeIfSamInterface(classDescriptor: ClassDescriptor): SimpleType? { + return resolver.resolveFunctionTypeIfSamInterface(classDescriptor) + } + } + private val functionTypesForSamInterfaces = storageManager.createCacheWithNullableValues() override fun resolveFunctionTypeIfSamInterface(classDescriptor: ClassDescriptor): SimpleType? { @@ -86,4 +93,71 @@ fun getFunctionTypeForAbstractMethod( function.builtIns, EMPTY, receiverType, parameterTypes, parameterNames, returnType, function.isSuspend ) -} \ No newline at end of file +} + +fun SamConversionResolver.getFunctionTypeForPossibleSamType(possibleSamType: UnwrappedType): UnwrappedType? = + getFunctionTypeForSamType(possibleSamType, this)?.unwrap() + +fun getFunctionTypeForSamType(samType: KotlinType, samResolver: SamConversionResolver): KotlinType? { + val unwrappedType = samType.unwrap() + if (unwrappedType is FlexibleType) { + val lower = getFunctionTypeForSamType(unwrappedType.lowerBound, samResolver) + val upper = getFunctionTypeForSamType(unwrappedType.upperBound, samResolver) + + assert((lower == null) == (upper == null)) { "Illegal flexible type: $unwrappedType" } + + if (lower == null || upper == null) return null + + return KotlinTypeFactory.flexibleType(lower, upper) + } else { + return getFunctionTypeForSamType(unwrappedType as SimpleType, samResolver) + } +} + +private fun getFunctionTypeForSamType(samType: SimpleType, samResolver: SamConversionResolver): SimpleType? { + // e.g. samType == Comparator? + val classifier = samType.constructor.declarationDescriptor + if (classifier !is ClassDescriptor) return null + + // Function2 + val functionTypeDefault = samResolver.resolveFunctionTypeIfSamInterface(classifier) ?: return null + val noProjectionsSamType = nonProjectionParametrization(samType) ?: return null + + // Function2? + val type = TypeSubstitutor.create(noProjectionsSamType).substitute(functionTypeDefault, Variance.IN_VARIANCE) + assert(type != null) { + "Substitution based on type with no projections '$noProjectionsSamType' should not end with conflict" + } + + val simpleType = type!!.asSimpleType() + return simpleType.makeNullableAsSpecified(samType.isMarkedNullable) +} + +// If type 'samType' contains no projection, then it's non-projection parametrization is 'samType' itself +// Else each projection type argument 'out/in A_i' (but star projections) is replaced with it's bound 'A_i' +// Star projections are treated specially: +// - If first upper bound of corresponding type parameter does not contain any type parameter of 'samType' class, +// then use this upper bound instead of star projection +// - Otherwise no non-projection parametrization exists for such 'samType' +// +// See Non-wildcard parametrization in JLS 8 p.9.9 for clarification +fun nonProjectionParametrization(samType: SimpleType): SimpleType? { + if (samType.arguments.none { it.projectionKind != Variance.INVARIANT }) return samType + val parameters = samType.constructor.parameters + val parametersSet = parameters.toSet() + + return samType.replace( + newArguments = samType.arguments.zip(parameters).map { + val (projection, parameter) = it + when { + projection.projectionKind == Variance.INVARIANT -> projection + + projection.isStarProjection -> + parameter.upperBounds.first().takeUnless { t -> + t.contains { it.constructor.declarationDescriptor in parametersSet } + }?.asTypeProjection() ?: return@nonProjectionParametrization null + + else -> projection.type.asTypeProjection() + } + }) +} 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 270df040409..62ccfc0aa6f 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 @@ -37,6 +37,8 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getValueArgumentsInParenthese import org.jetbrains.kotlin.resolve.calls.components.SamConversionTransformer import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode +import org.jetbrains.kotlin.resolve.sam.SamConversionResolver +import org.jetbrains.kotlin.resolve.sam.getFunctionTypeForPossibleSamType import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.isError import org.jetbrains.kotlin.types.typeUtil.isTypeParameter @@ -127,7 +129,7 @@ fun KtCallExpression.canMoveLambdaOutsideParentheses(): Boolean { val referenceArgumentCount = valueArguments.count { it.getArgumentExpression() is KtCallableReferenceExpression } val resolutionFacade = getResolutionFacade() - val samConversionTransformer = resolutionFacade.frontendService() + val samConversionTransformer = resolutionFacade.frontendService() val languageVersionSettings = resolutionFacade.frontendService() val bindingContext = analyze(resolutionFacade, BodyResolveMode.PARTIAL) @@ -154,7 +156,7 @@ fun KtCallExpression.canMoveLambdaOutsideParentheses(): Boolean { private fun FunctionDescriptor.allowsMoveOfLastParameterOutsideParentheses( lambdaAndCallableReferencesInOriginalCallCount: Int, - samConversionTransformer: SamConversionTransformer, + samConversionTransformer: SamConversionResolver, newInferenceEnabled: Boolean ): Boolean { fun KotlinType.allowsMoveOutsideParentheses(): Boolean {