diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestWithStdlibGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestWithStdlibGenerated.java index f2b331003c1..e2a019242af 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestWithStdlibGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestWithStdlibGenerated.java @@ -1839,6 +1839,11 @@ public class FirOldFrontendDiagnosticsTestWithStdlibGenerated extends AbstractFi public void testResolutionInOldInference() throws Exception { runTest("compiler/testData/diagnostics/testsWithStdLib/factoryPattern/resolutionInOldInference.kt"); } + + @TestMetadata("returnFromInlineLambda.kt") + public void testReturnFromInlineLambda() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/factoryPattern/returnFromInlineLambda.kt"); + } } @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/forInArrayLoop") diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java index 2158c9b7c77..7f4905ac2ac 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java @@ -274,6 +274,7 @@ public interface BindingContext { WritableSlice PRIMITIVE_NUMERIC_COMPARISON_INFO = Slices.createSimpleSlice(); WritableSlice> NEW_INFERENCE_CATCH_EXCEPTION_PARAMETER = Slices.createSimpleSlice(); + WritableSlice NEW_INFERENCE_IS_LAMBDA_FOR_OVERLOAD_RESOLUTION_INLINE = Slices.createSimpleSlice(); @SuppressWarnings("UnusedDeclaration") @Deprecated // This field is needed only for the side effects of its initializer diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt index da7910a85bf..d2380782a32 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt @@ -8,19 +8,14 @@ package org.jetbrains.kotlin.resolve.calls.tower import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.kotlin.builtins.KotlinBuiltIns.isPrimitiveTypeOrNullablePrimitiveType import org.jetbrains.kotlin.builtins.KotlinBuiltIns.isUnderKotlinPackage -import org.jetbrains.kotlin.builtins.UnsignedTypes import org.jetbrains.kotlin.builtins.createFunctionType -import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.psi.KtCallableReferenceExpression -import org.jetbrains.kotlin.psi.KtExpression -import org.jetbrains.kotlin.psi.KtPsiUtil -import org.jetbrains.kotlin.psi.KtReturnExpression +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getBinaryWithTypeParent import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis import org.jetbrains.kotlin.resolve.* @@ -40,6 +35,7 @@ import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns +import org.jetbrains.kotlin.resolve.inline.InlineUtil import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.expressions.DoubleColonExpressionResolver @@ -48,7 +44,6 @@ import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo import org.jetbrains.kotlin.types.refinement.TypeRefinement import org.jetbrains.kotlin.types.typeUtil.isUnit import org.jetbrains.kotlin.types.typeUtil.makeNullable -import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addToStdlib.safeAs data class LambdaContextInfo( @@ -317,6 +312,17 @@ class KotlinResolutionCallbacksImpl( return convertSignedConstantToUnsigned(argumentExpression) } + override fun recordInlinabilityOfLambda(lambdas: Set>) { + val call = lambdas.first().value.atom.psiCallArgument.valueArgument as? KtLambdaArgument ?: return + val literal = call.getLambdaExpression()?.functionLiteral ?: return + val isLambdaInline = lambdas.all { (candidate, atom) -> + if (!InlineUtil.isInline(candidate.resolvedCall.candidateDescriptor)) return + val valueParameterDescriptor = candidate.resolvedCall.argumentToCandidateParameter[atom.atom] ?: return + InlineUtil.isInlineParameter(valueParameterDescriptor) + }.takeIf { it } + trace.record(BindingContext.NEW_INFERENCE_IS_LAMBDA_FOR_OVERLOAD_RESOLUTION_INLINE, literal, isLambdaInline) + } + private fun convertSignedConstantToUnsigned(expression: KtExpression): IntegerValueTypeConstant? { val constant = trace[BindingContext.COMPILE_TIME_VALUE, expression] if (constant !is IntegerValueTypeConstant || !constantCanBeConvertedToUnsigned(constant)) return null diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineUtil.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineUtil.java index a0f43724f8a..4d151d00a59 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineUtil.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineUtil.java @@ -99,6 +99,11 @@ public class InlineUtil { if (containingFunctionDescriptor == null) return false; while (canBeInlineArgument(containingFunction) && fromFunction != containingFunctionDescriptor) { + Boolean isLambdaDefinitelyInline = bindingContext.get(BindingContext.NEW_INFERENCE_IS_LAMBDA_FOR_OVERLOAD_RESOLUTION_INLINE, containingFunction); + if (isLambdaDefinitelyInline != null) { + return isLambdaDefinitelyInline; + } + if (!isInlinedArgument((KtFunction) containingFunction, bindingContext, true)) { return false; } 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 0d2b02fc0c4..6bfcd1aacd1 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 @@ -6,11 +6,8 @@ package org.jetbrains.kotlin.resolve.calls.components import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.config.LanguageFeature 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 @@ -20,7 +17,6 @@ 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.resolve.constants.IntegerValueTypeConstant -import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.StubType import org.jetbrains.kotlin.types.UnwrappedType @@ -85,4 +81,6 @@ interface KotlinResolutionCallbacks { fun disableContractsIfNecessary(resolvedAtom: ResolvedCallAtom) fun convertSignedConstantToUnsigned(argument: KotlinCallArgument): IntegerValueTypeConstant? + + fun recordInlinabilityOfLambda(atom: Set>) } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt index bab59ced937..53e217c4ca3 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt @@ -16,8 +16,6 @@ import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintS import org.jetbrains.kotlin.resolve.calls.inference.components.TrivialConstraintTypeInferenceOracle import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage.Empty.hasContradiction import org.jetbrains.kotlin.resolve.calls.inference.model.ExpectedTypeConstraintPosition -import org.jetbrains.kotlin.resolve.calls.inference.model.LambdaArgumentConstraintPosition -import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableTypeConstructor import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.tower.forceResolution import org.jetbrains.kotlin.types.ErrorUtils @@ -113,6 +111,9 @@ class KotlinCallCompleter( val diagnosticHolderForLambda = KotlinDiagnosticsHolder.SimpleHolder() val iterator = newAtoms.entries.iterator() val (firstCandidate, firstAtom) = iterator.next() + + resolutionCallbacks.recordInlinabilityOfLambda(lambdas.entries) + val results = postponedArgumentsAnalyzer.analyzeLambda( firstCandidate.getSystem().asPostponedArgumentsAnalyzerContext(), resolutionCallbacks, diff --git a/compiler/testData/diagnostics/testsWithStdLib/factoryPattern/returnFromInlineLambda.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/factoryPattern/returnFromInlineLambda.fir.kt new file mode 100644 index 00000000000..ed92d7cd852 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/factoryPattern/returnFromInlineLambda.fir.kt @@ -0,0 +1,51 @@ +// !LANGUAGE: +NewInference +OverloadResolutionByLambdaReturnType +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE -UNUSED_EXPRESSION -EXPERIMENTAL_API_USAGE -EXPERIMENTAL_UNSIGNED_LITERALS +// ISSUE: KT-11265 + +// FILE: OverloadResolutionByLambdaReturnType.kt + +package kotlin + +annotation class OverloadResolutionByLambdaReturnType + +// FILE: main.kt + +import kotlin.OverloadResolutionByLambdaReturnType + +inline fun Array.myFlatMap(transform: (T) -> Iterable): List { + TODO() +} + +@OverloadResolutionByLambdaReturnType +@JvmName("seqFlatMap") +inline fun Array.myFlatMap(transform: (T) -> Sequence): List { + TODO() +} + +fun String.toList(): List = null!! + +fun test_1(a: Array, b: Boolean) { + a.myFlatMap { it.toList().ifEmpty { return } } + a.myFlatMap { + if (b) return + it.toList() + } +} + +fun Array.noInlineFlatMap(transform: (T) -> Iterable): List { + TODO() +} + +@OverloadResolutionByLambdaReturnType +@JvmName("noInlineSeqFlatMap") +fun Array.noInlineFlatMap(transform: (T) -> Sequence): List { + TODO() +} + +fun test_2(a: Array, b: Boolean) { + a.noInlineFlatMap { it.toList().ifEmpty { return } } + a.noInlineFlatMap { + if (b) return + it.toList() + } +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/factoryPattern/returnFromInlineLambda.kt b/compiler/testData/diagnostics/testsWithStdLib/factoryPattern/returnFromInlineLambda.kt new file mode 100644 index 00000000000..b53de27da0b --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/factoryPattern/returnFromInlineLambda.kt @@ -0,0 +1,51 @@ +// !LANGUAGE: +NewInference +OverloadResolutionByLambdaReturnType +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE -UNUSED_EXPRESSION -EXPERIMENTAL_API_USAGE -EXPERIMENTAL_UNSIGNED_LITERALS +// ISSUE: KT-11265 + +// FILE: OverloadResolutionByLambdaReturnType.kt + +package kotlin + +annotation class OverloadResolutionByLambdaReturnType + +// FILE: main.kt + +import kotlin.OverloadResolutionByLambdaReturnType + +inline fun Array.myFlatMap(transform: (T) -> Iterable): List { + TODO() +} + +@OverloadResolutionByLambdaReturnType +@JvmName("seqFlatMap") +inline fun Array.myFlatMap(transform: (T) -> Sequence): List { + TODO() +} + +fun String.toList(): List = null!! + +fun test_1(a: Array, b: Boolean) { + a.myFlatMap { it.toList().ifEmpty { return } } + a.myFlatMap { + if (b) return + it.toList() + } +} + +fun Array.noInlineFlatMap(transform: (T) -> Iterable): List { + TODO() +} + +@OverloadResolutionByLambdaReturnType +@JvmName("noInlineSeqFlatMap") +fun Array.noInlineFlatMap(transform: (T) -> Sequence): List { + TODO() +} + +fun test_2(a: Array, b: Boolean) { + a.noInlineFlatMap { it.toList().ifEmpty { return } } + a.noInlineFlatMap { + if (b) return + it.toList() + } +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/factoryPattern/returnFromInlineLambda.txt b/compiler/testData/diagnostics/testsWithStdLib/factoryPattern/returnFromInlineLambda.txt new file mode 100644 index 00000000000..256a5c746dc --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/factoryPattern/returnFromInlineLambda.txt @@ -0,0 +1,19 @@ +package + +public fun test_1(/*0*/ a: kotlin.Array, /*1*/ b: kotlin.Boolean): kotlin.Unit +public fun test_2(/*0*/ a: kotlin.Array, /*1*/ b: kotlin.Boolean): kotlin.Unit +public inline fun kotlin.Array.myFlatMap(/*0*/ transform: (T) -> kotlin.collections.Iterable): kotlin.collections.List +@kotlin.OverloadResolutionByLambdaReturnType @kotlin.jvm.JvmName(name = "seqFlatMap") public inline fun kotlin.Array.myFlatMap(/*0*/ transform: (T) -> kotlin.sequences.Sequence): kotlin.collections.List +public fun kotlin.Array.noInlineFlatMap(/*0*/ transform: (T) -> kotlin.collections.Iterable): kotlin.collections.List +@kotlin.OverloadResolutionByLambdaReturnType @kotlin.jvm.JvmName(name = "noInlineSeqFlatMap") public fun kotlin.Array.noInlineFlatMap(/*0*/ transform: (T) -> kotlin.sequences.Sequence): kotlin.collections.List +public fun kotlin.String.toList(): kotlin.collections.List + +package kotlin { + + public final annotation class OverloadResolutionByLambdaReturnType : kotlin.Annotation { + public constructor OverloadResolutionByLambdaReturnType() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java index 9ae5e570849..7c23039fa5a 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java @@ -2854,6 +2854,11 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW public void testResolutionInOldInference() throws Exception { runTest("compiler/testData/diagnostics/testsWithStdLib/factoryPattern/resolutionInOldInference.kt"); } + + @TestMetadata("returnFromInlineLambda.kt") + public void testReturnFromInlineLambda() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/factoryPattern/returnFromInlineLambda.kt"); + } } @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/forInArrayLoop") diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java index 6264a49dd55..aa692517223 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java @@ -2854,6 +2854,11 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno public void testResolutionInOldInference() throws Exception { runTest("compiler/testData/diagnostics/testsWithStdLib/factoryPattern/resolutionInOldInference.kt"); } + + @TestMetadata("returnFromInlineLambda.kt") + public void testReturnFromInlineLambda() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/factoryPattern/returnFromInlineLambda.kt"); + } } @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/forInArrayLoop")