diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java index d140450e211..fc77efafad8 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java @@ -8469,6 +8469,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/generics/kt30590.kt"); } + @TestMetadata("kt34729.kt") + public void testKt34729() throws Exception { + runTest("compiler/testData/diagnostics/tests/generics/kt34729.kt"); + } + @TestMetadata("kt5508.kt") public void testKt5508() throws Exception { runTest("compiler/testData/diagnostics/tests/generics/kt5508.kt"); @@ -10537,6 +10542,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/completion"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); } + @TestMetadata("anonymousFunction.kt") + public void testAnonymousFunction() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/completion/anonymousFunction.kt"); + } + @TestMetadata("basic.kt") public void testBasic() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/completion/basic.kt"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt index c16fa091a8d..c636e8483c0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt @@ -273,6 +273,7 @@ class DiagnosticReporterByTrackingStrategy( is ArgumentConstraintPosition -> position.argument is ReceiverConstraintPosition -> position.argument is LHSArgumentConstraintPosition -> position.argument + is LambdaArgumentConstraintPosition -> position.lambda.atom else -> null } argument?.let { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingVisitor.java index 86dfae0c942..4e5b8bbf692 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingVisitor.java @@ -56,6 +56,7 @@ import static org.jetbrains.kotlin.resolve.BindingContext.*; import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT; import static org.jetbrains.kotlin.types.TypeUtils.*; import static org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils.*; +import static org.jetbrains.kotlin.types.expressions.ExpressionTypingServices.getNewInferenceLambdaInfo; import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.*; public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { @@ -945,17 +946,6 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { replaceJumpOutPossible(true); } - @Nullable - private static KotlinResolutionCallbacksImpl.LambdaInfo getNewInferenceLambdaInfo( - @NotNull ExpressionTypingContext context, - @NotNull KtElement function - ) { - if (function instanceof KtFunction) { - return context.trace.get(BindingContext.NEW_INFERENCE_LAMBDA_INFO, (KtFunction) function); - } - return null; - } - @NotNull private static KotlinType getFunctionExpectedReturnType( @NotNull FunctionDescriptor descriptor, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingServices.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingServices.java index 59b2e7c575f..1d2e92af8bb 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingServices.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingServices.java @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext; import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo; import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue; import org.jetbrains.kotlin.resolve.calls.tower.KotlinResolutionCallbacksImpl; +import org.jetbrains.kotlin.resolve.calls.tower.LambdaContextInfo; import org.jetbrains.kotlin.resolve.scopes.*; import org.jetbrains.kotlin.types.ErrorUtils; import org.jetbrains.kotlin.types.KotlinType; @@ -224,7 +225,11 @@ public class ExpressionTypingServices { trace, functionInnerScope, dataFlowInfo, NO_EXPECTED_TYPE, getLanguageVersionSettings(), expressionTypingComponents.dataFlowValueFactory ); + + KotlinResolutionCallbacksImpl.LambdaInfo lambdaInfo = getNewInferenceLambdaInfo(context, function); + context = updateContextFromNILambdaInfo(lambdaInfo, context); KotlinTypeInfo typeInfo = expressionTypingFacade.getTypeInfo(bodyExpression, context, function.hasBlockBody()); + updateLambdaContextInfoForAnonymousFunction(lambdaInfo, typeInfo, context); KotlinType type = typeInfo.getType(); if (type != null) { @@ -235,6 +240,43 @@ public class ExpressionTypingServices { } } + private static void updateLambdaContextInfoForAnonymousFunction( + @Nullable KotlinResolutionCallbacksImpl.LambdaInfo lambdaInfo, + @NotNull KotlinTypeInfo bodyExpressionTypeInfo, + @NotNull ExpressionTypingContext context + ) { + if (lambdaInfo == null) return; + + LambdaContextInfo contextInfo = lambdaInfo.getLastExpressionInfo(); + contextInfo.setTypeInfo(bodyExpressionTypeInfo); + contextInfo.setDataFlowInfoAfter(null); + contextInfo.setLexicalScope(context.scope); + contextInfo.setTrace(context.trace); + } + + private static ExpressionTypingContext updateContextFromNILambdaInfo( + @Nullable KotlinResolutionCallbacksImpl.LambdaInfo lambdaInfo, + @NotNull ExpressionTypingContext context + ) { + if (lambdaInfo != null) { + context = context + .replaceContextDependency(lambdaInfo.getContextDependency()) + .replaceExpectedType(lambdaInfo.getExpectedType()); + } + return context; + } + + @Nullable + public static KotlinResolutionCallbacksImpl.LambdaInfo getNewInferenceLambdaInfo( + @NotNull ExpressionTypingContext context, + @NotNull KtElement function + ) { + if (function instanceof KtFunction) { + return context.trace.get(BindingContext.NEW_INFERENCE_LAMBDA_INFO, (KtFunction) function); + } + return null; + } + /** * Visits block statements propagating data flow information from the first to the last. * Determines block returned type and data flow information at the end of the block AND 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 d5ab883d0ce..1729daabf11 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 @@ -139,7 +139,6 @@ class PostponedArgumentsAnalyzer( if (returnArguments.isEmpty()) { val unitType = lambda.returnType.builtIns.unitType val lambdaReturnType = lambda.returnType.let(::substitute) - c.getBuilder().addSubtypeConstraint(lambdaReturnType, unitType, LambdaArgumentConstraintPosition(lambda)) c.getBuilder().addSubtypeConstraint(unitType, lambdaReturnType, LambdaArgumentConstraintPosition(lambda)) } diff --git a/compiler/testData/diagnostics/tests/functionAsExpression/InferenceParametersTypes.kt b/compiler/testData/diagnostics/tests/functionAsExpression/InferenceParametersTypes.kt index 4f6e830cd0b..b458f865a91 100644 --- a/compiler/testData/diagnostics/tests/functionAsExpression/InferenceParametersTypes.kt +++ b/compiler/testData/diagnostics/tests/functionAsExpression/InferenceParametersTypes.kt @@ -12,7 +12,7 @@ fun test(a: (Int) -> Int) { } fun test2(a: () -> List) { - test2(fun () = listOf()) + test2(fun () = listOf()) } val a: (Int) -> Unit = fun(x) { checkSubtype(x) } diff --git a/compiler/testData/diagnostics/tests/generics/kt34729.fir.kt b/compiler/testData/diagnostics/tests/generics/kt34729.fir.kt new file mode 100644 index 00000000000..017f96bd1b4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/kt34729.fir.kt @@ -0,0 +1,19 @@ +// !WITH_NEW_INFERENCE +// !DIAGNOSTICS: -UNUSED_PARAMETER +// !LANGUAGE: +NewInference + +interface ILength { + val length: Int +} + +class Impl(override val length: Int) : ILength + +fun foo(a: (Int) -> T) = 0 +fun bar(a: (Int) -> T) { + a(42).length +} + +fun test() { + foo { } + bar { } +} diff --git a/compiler/testData/diagnostics/tests/generics/kt34729.kt b/compiler/testData/diagnostics/tests/generics/kt34729.kt new file mode 100644 index 00000000000..665129cf9bd --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/kt34729.kt @@ -0,0 +1,19 @@ +// !WITH_NEW_INFERENCE +// !DIAGNOSTICS: -UNUSED_PARAMETER +// !LANGUAGE: +NewInference + +interface ILength { + val length: Int +} + +class Impl(override val length: Int) : ILength + +fun foo(a: (Int) -> T) = 0 +fun bar(a: (Int) -> T) { + a(42).length +} + +fun test() { + foo { } + bar { } +} diff --git a/compiler/testData/diagnostics/tests/generics/kt34729.txt b/compiler/testData/diagnostics/tests/generics/kt34729.txt new file mode 100644 index 00000000000..9c7df19323a --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/kt34729.txt @@ -0,0 +1,20 @@ +package + +public fun bar(/*0*/ a: (kotlin.Int) -> T): kotlin.Unit +public fun foo(/*0*/ a: (kotlin.Int) -> T): kotlin.Int +public fun test(): kotlin.Unit + +public interface ILength { + public abstract val length: kotlin.Int + 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 +} + +public final class Impl : ILength { + public constructor Impl(/*0*/ length: kotlin.Int) + public open override /*1*/ val length: kotlin.Int + 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/testData/diagnostics/tests/inference/completion/anonymousFunction.fir.kt b/compiler/testData/diagnostics/tests/inference/completion/anonymousFunction.fir.kt new file mode 100644 index 00000000000..2bf0ecb995a --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/completion/anonymousFunction.fir.kt @@ -0,0 +1,22 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun take(fn: () -> List) {} +fun inferFromLambda(fn: () -> L): L = TODO() + +fun materialize(): T = TODO() +fun id(arg: I) = arg + +fun testFunctions() { + take { materialize() } + take(fun() = materialize()) + take(fun(): List = materialize()) + take(fun(): List { + return materialize() + }) +} + +fun testNestedCalls() { + id(inferFromLambda { materialize() }) + id(inferFromLambda(fun() = materialize())) +} diff --git a/compiler/testData/diagnostics/tests/inference/completion/anonymousFunction.kt b/compiler/testData/diagnostics/tests/inference/completion/anonymousFunction.kt new file mode 100644 index 00000000000..2bf0ecb995a --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/completion/anonymousFunction.kt @@ -0,0 +1,22 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun take(fn: () -> List) {} +fun inferFromLambda(fn: () -> L): L = TODO() + +fun materialize(): T = TODO() +fun id(arg: I) = arg + +fun testFunctions() { + take { materialize() } + take(fun() = materialize()) + take(fun(): List = materialize()) + take(fun(): List { + return materialize() + }) +} + +fun testNestedCalls() { + id(inferFromLambda { materialize() }) + id(inferFromLambda(fun() = materialize())) +} diff --git a/compiler/testData/diagnostics/tests/inference/completion/anonymousFunction.txt b/compiler/testData/diagnostics/tests/inference/completion/anonymousFunction.txt new file mode 100644 index 00000000000..ba09cc8ce83 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/completion/anonymousFunction.txt @@ -0,0 +1,8 @@ +package + +public fun id(/*0*/ arg: I): I +public fun inferFromLambda(/*0*/ fn: () -> L): L +public fun materialize(): T +public fun take(/*0*/ fn: () -> kotlin.collections.List): kotlin.Unit +public fun testFunctions(): kotlin.Unit +public fun testNestedCalls(): kotlin.Unit diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 9e37a423bd3..f91b807dda1 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -8476,6 +8476,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/generics/kt30590.kt"); } + @TestMetadata("kt34729.kt") + public void testKt34729() throws Exception { + runTest("compiler/testData/diagnostics/tests/generics/kt34729.kt"); + } + @TestMetadata("kt5508.kt") public void testKt5508() throws Exception { runTest("compiler/testData/diagnostics/tests/generics/kt5508.kt"); @@ -10544,6 +10549,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/completion"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); } + @TestMetadata("anonymousFunction.kt") + public void testAnonymousFunction() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/completion/anonymousFunction.kt"); + } + @TestMetadata("basic.kt") public void testBasic() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/completion/basic.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 303899fca6f..d189eb5be74 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -8471,6 +8471,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/generics/kt30590.kt"); } + @TestMetadata("kt34729.kt") + public void testKt34729() throws Exception { + runTest("compiler/testData/diagnostics/tests/generics/kt34729.kt"); + } + @TestMetadata("kt5508.kt") public void testKt5508() throws Exception { runTest("compiler/testData/diagnostics/tests/generics/kt5508.kt"); @@ -10539,6 +10544,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/completion"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); } + @TestMetadata("anonymousFunction.kt") + public void testAnonymousFunction() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/completion/anonymousFunction.kt"); + } + @TestMetadata("basic.kt") public void testBasic() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/completion/basic.kt");