diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java index 9640fad1679..86fdb5aacba 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java @@ -10434,6 +10434,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/inference/returningLambdaInSuspendContext.kt"); } + @TestMetadata("simpleLambdaInCallWithAnotherLambdaWithBuilderInference.kt") + public void testSimpleLambdaInCallWithAnotherLambdaWithBuilderInference() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/simpleLambdaInCallWithAnotherLambdaWithBuilderInference.kt"); + } + @TestMetadata("skipedUnresolvedInBuilderInferenceWithStubReceiverType.kt") public void testSkipedUnresolvedInBuilderInferenceWithStubReceiverType() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/skipedUnresolvedInBuilderInferenceWithStubReceiverType.kt"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt index d3800768ac1..f3132ab0c1a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt @@ -110,6 +110,12 @@ class LambdaKotlinCallArgumentImpl( ) : PSIFunctionKotlinCallArgument(outerCallContext, valueArgument, dataFlowInfoBeforeThisArgument, argumentName) { override val ktFunction get() = ktLambdaExpression.functionLiteral override val expression get() = containingBlockForLambda + + override var hasBuilderInferenceAnnotation = false + set(value) { + assert(!field) + field = value + } } class FunctionExpressionImpl( diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponedArgumentsAnalyzer.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponedArgumentsAnalyzer.kt index b3480170c80..2a82e15663f 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponedArgumentsAnalyzer.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponedArgumentsAnalyzer.kt @@ -187,7 +187,7 @@ class PostponedArgumentsAnalyzer( lambda.setAnalyzedResults(returnArgumentsInfo, subResolvedKtPrimitives) - if (inferenceSession != null) { + if (inferenceSession != null && lambda.atom.hasBuilderInferenceAnnotation) { val storageSnapshot = c.getBuilder().currentStorage() val postponedVariables = inferenceSession.inferPostponedVariables(lambda, storageSnapshot, diagnosticHolder) 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 8117f10a9eb..eb366d626a7 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 @@ -238,6 +238,10 @@ internal object PostponedVariablesInitializerResolutionPart : ResolutionPart() { if (!callComponents.statelessCallbacks.isCoroutineCall(argument, parameter)) continue val receiverType = parameter.type.getReceiverTypeFromFunctionType() ?: continue + if (argument is LambdaKotlinCallArgument && !argument.hasBuilderInferenceAnnotation) { + argument.hasBuilderInferenceAnnotation = true + } + for (freshVariable in resolvedCall.freshVariablesSubstitutor.freshVariables) { if (resolvedCall.typeArgumentMappingByOriginal.getTypeArgument(freshVariable.originalTypeParameter) is SimpleTypeArgument) continue diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallArguments.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallArguments.kt index fd9fdd12974..514f9f58341 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallArguments.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallArguments.kt @@ -52,6 +52,14 @@ interface LambdaKotlinCallArgument : PostponableKotlinCallArgument { override val isSpread: Boolean get() = false + /* + * Builder inference is supported only for lambdas (so it's implemented only in `LambdaKotlinCallArgumentImpl`), + * anonymous functions aren't supported + */ + var hasBuilderInferenceAnnotation: Boolean + get() = false + set(value) {} + /** * parametersTypes == null means, that there is no declared arguments * null inside array means that this type is not declared explicitly diff --git a/compiler/testData/diagnostics/tests/inference/simpleLambdaInCallWithAnotherLambdaWithBuilderInference.fir.kt b/compiler/testData/diagnostics/tests/inference/simpleLambdaInCallWithAnotherLambdaWithBuilderInference.fir.kt new file mode 100644 index 00000000000..157ae3b5566 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/simpleLambdaInCallWithAnotherLambdaWithBuilderInference.fir.kt @@ -0,0 +1,20 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -DEPRECATION -EXPERIMENTAL_IS_NOT_ENABLED -UNUSED_VARIABLE +// WITH_RUNTIME + +import kotlin.experimental.ExperimentalTypeInference + +@UseExperimental(ExperimentalTypeInference::class) +fun combined( + check: () -> Unit, + @BuilderInference block: TestInterface.() -> Unit +): R = TODO() + +interface TestInterface { + fun emit(r: R) +} + +fun test() { + val ret = combined({ }) { + emit(1) + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/simpleLambdaInCallWithAnotherLambdaWithBuilderInference.kt b/compiler/testData/diagnostics/tests/inference/simpleLambdaInCallWithAnotherLambdaWithBuilderInference.kt new file mode 100644 index 00000000000..72bcb817bda --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/simpleLambdaInCallWithAnotherLambdaWithBuilderInference.kt @@ -0,0 +1,20 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -DEPRECATION -EXPERIMENTAL_IS_NOT_ENABLED -UNUSED_VARIABLE +// WITH_RUNTIME + +import kotlin.experimental.ExperimentalTypeInference + +@UseExperimental(ExperimentalTypeInference::class) +fun combined( + check: () -> Unit, + @BuilderInference block: TestInterface.() -> Unit +): R = TODO() + +interface TestInterface { + fun emit(r: R) +} + +fun test() { + val ret = combined({ }) { + emit(1) + } +} diff --git a/compiler/testData/diagnostics/tests/inference/simpleLambdaInCallWithAnotherLambdaWithBuilderInference.txt b/compiler/testData/diagnostics/tests/inference/simpleLambdaInCallWithAnotherLambdaWithBuilderInference.txt new file mode 100644 index 00000000000..c8f53812378 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/simpleLambdaInCallWithAnotherLambdaWithBuilderInference.txt @@ -0,0 +1,11 @@ +package + +@kotlin.UseExperimental(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun combined(/*0*/ check: () -> kotlin.Unit, /*1*/ @kotlin.BuilderInference block: TestInterface.() -> kotlin.Unit): R +public fun test(): kotlin.Unit + +public interface TestInterface { + public abstract fun emit(/*0*/ r: R): kotlin.Unit + 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/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 9f26dc4b9c5..9119fb7febf 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -10441,6 +10441,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali runTest("compiler/testData/diagnostics/tests/inference/returningLambdaInSuspendContext.kt"); } + @TestMetadata("simpleLambdaInCallWithAnotherLambdaWithBuilderInference.kt") + public void testSimpleLambdaInCallWithAnotherLambdaWithBuilderInference() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/simpleLambdaInCallWithAnotherLambdaWithBuilderInference.kt"); + } + @TestMetadata("skipedUnresolvedInBuilderInferenceWithStubReceiverType.kt") public void testSkipedUnresolvedInBuilderInferenceWithStubReceiverType() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/skipedUnresolvedInBuilderInferenceWithStubReceiverType.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 462af9f6f85..691053e09f5 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -10436,6 +10436,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/inference/returningLambdaInSuspendContext.kt"); } + @TestMetadata("simpleLambdaInCallWithAnotherLambdaWithBuilderInference.kt") + public void testSimpleLambdaInCallWithAnotherLambdaWithBuilderInference() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/simpleLambdaInCallWithAnotherLambdaWithBuilderInference.kt"); + } + @TestMetadata("skipedUnresolvedInBuilderInferenceWithStubReceiverType.kt") public void testSkipedUnresolvedInBuilderInferenceWithStubReceiverType() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/skipedUnresolvedInBuilderInferenceWithStubReceiverType.kt");