diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/InferenceCompletion.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/InferenceCompletion.kt index cd27143145f..0165baa48de 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/InferenceCompletion.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/InferenceCompletion.kt @@ -6,8 +6,8 @@ package org.jetbrains.kotlin.fir.resolve.calls import org.jetbrains.kotlin.fir.expressions.* -import org.jetbrains.kotlin.fir.types.ConeIntegerLiteralType import org.jetbrains.kotlin.fir.returnExpressions +import org.jetbrains.kotlin.fir.types.ConeIntegerLiteralType import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.ConeTypeVariable import org.jetbrains.kotlin.fir.types.FirTypeRef @@ -157,11 +157,6 @@ class ConstraintSystemCompleter(val components: InferenceComponents) { for (lambdaAtom in candidate.postponedAtoms.filterIsInstance()) { result.addIfNotNull(lambdaAtom.typeVariableForLambdaReturnType.toTypeConstructor()) - if (lambdaAtom.analyzed) { - for (firStatement in lambdaAtom.returnStatements) { - firStatement.collectAllTypeVariables() - } - } } } } @@ -231,32 +226,32 @@ class ConstraintSystemCompleter(val components: InferenceComponents) { private fun FirStatement.processAllContainingCallCandidates(processBlocks: Boolean, processor: (Candidate) -> Unit) { when (this) { is FirFunctionCall -> { - processCandidateIfApplicable(processor) + processCandidateIfApplicable(processor, processBlocks) this.arguments.forEach { it.processAllContainingCallCandidates(processBlocks, processor) } } is FirWhenExpression -> { - processCandidateIfApplicable(processor) + processCandidateIfApplicable(processor, processBlocks) this.branches.forEach { it.result.processAllContainingCallCandidates(processBlocks, processor) } } is FirTryExpression -> { - processCandidateIfApplicable(processor) + processCandidateIfApplicable(processor, processBlocks) tryBlock.processAllContainingCallCandidates(processBlocks, processor) catches.forEach { it.block.processAllContainingCallCandidates(processBlocks, processor) } } is FirCheckNotNullCall -> { - processCandidateIfApplicable(processor) + processCandidateIfApplicable(processor, processBlocks) this.arguments.forEach { it.processAllContainingCallCandidates(processBlocks, processor) } } is FirQualifiedAccessExpression -> { - processCandidateIfApplicable(processor) + processCandidateIfApplicable(processor, processBlocks) } is FirVariableAssignment -> { - processCandidateIfApplicable(processor) + processCandidateIfApplicable(processor, processBlocks) rValue.processAllContainingCallCandidates(processBlocks, processor) } @@ -268,14 +263,26 @@ class ConstraintSystemCompleter(val components: InferenceComponents) { } is FirDelegatedConstructorCall -> { - processCandidateIfApplicable(processor) + processCandidateIfApplicable(processor, processBlocks) this.arguments.forEach { it.processAllContainingCallCandidates(processBlocks, processor) } } } } - private inline fun FirResolvable.processCandidateIfApplicable(processor: (Candidate) -> Unit) { - (calleeReference as? FirNamedReferenceWithCandidate)?.candidate?.let(processor) + private fun FirResolvable.processCandidateIfApplicable( + processor: (Candidate) -> Unit, + processBlocks: Boolean + ) { + val candidate = (calleeReference as? FirNamedReferenceWithCandidate)?.candidate ?: return + processor(candidate) + + for (atom in candidate.postponedAtoms) { + if (atom !is ResolvedLambdaAtom || !atom.analyzed) continue + + atom.returnStatements.forEach { + it.processAllContainingCallCandidates(processBlocks, processor) + } + } } private fun canWeAnalyzeIt(c: KotlinConstraintSystemCompleter.Context, argument: PostponedResolvedAtomMarker): Boolean { diff --git a/compiler/fir/resolve/testData/resolve/inference/nestedLambdas.kt b/compiler/fir/resolve/testData/resolve/inference/nestedLambdas.kt new file mode 100644 index 00000000000..ad82790b423 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/inference/nestedLambdas.kt @@ -0,0 +1,21 @@ +fun myRun(computable: () -> T): T = TODO() + +interface Inv +interface MyMap { + val k: K + val v: V +} + +val w: Inv = TODO() + +public fun Inv.associateBy1(keySelector: (X) -> K): MyMap = TODO() + +val x = myRun { + w.associateBy1 { f -> f.length } +} + +fun foo(m: MyMap) {} + +fun main() { + foo(x) +} diff --git a/compiler/fir/resolve/testData/resolve/inference/nestedLambdas.txt b/compiler/fir/resolve/testData/resolve/inference/nestedLambdas.txt new file mode 100644 index 00000000000..bd313b4538d --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/inference/nestedLambdas.txt @@ -0,0 +1,32 @@ +FILE: nestedLambdas.kt + public final fun myRun(computable: R|() -> T|): R|T| { + ^myRun R|kotlin/TODO|() + } + public abstract interface Inv : R|kotlin/Any| { + } + public abstract interface MyMap : R|kotlin/Any| { + public abstract val k: R|K| + public get(): R|K| + + public abstract val v: R|V| + public get(): R|V| + + } + public final val w: R|Inv| = R|kotlin/TODO|() + public get(): R|Inv| + public final fun R|Inv|.associateBy1(keySelector: R|(X) -> K|): R|MyMap| { + ^associateBy1 R|kotlin/TODO|() + } + public final val x: R|MyMap| = R|/myRun||>( = myRun@fun (): R|MyMap| { + R|/w|.R|/associateBy1|( = associateBy1@fun (f: R|kotlin/String|): R|kotlin/Int| { + R|/f|.R|kotlin/String.length| + } + ) + } + ) + public get(): R|MyMap| + public final fun foo(m: R|MyMap|): R|kotlin/Unit| { + } + public final fun main(): R|kotlin/Unit| { + R|/foo|(R|/x|) + } diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java index df3fd3f0a2a..3340ac63189 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java @@ -904,6 +904,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/resolve/testData/resolve/inference"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @TestMetadata("nestedLambdas.kt") + public void testNestedLambdas() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/inference/nestedLambdas.kt"); + } + @TestMetadata("receiverWithCapturedType.kt") public void testReceiverWithCapturedType() throws Exception { runTest("compiler/fir/resolve/testData/resolve/inference/receiverWithCapturedType.kt"); diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java index fff453285a7..90404bb7548 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java @@ -904,6 +904,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/resolve/testData/resolve/inference"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @TestMetadata("nestedLambdas.kt") + public void testNestedLambdas() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/inference/nestedLambdas.kt"); + } + @TestMetadata("receiverWithCapturedType.kt") public void testReceiverWithCapturedType() throws Exception { runTest("compiler/fir/resolve/testData/resolve/inference/receiverWithCapturedType.kt"); diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/inference/delegateExpressionAsLambda.fir.kt b/compiler/testData/diagnostics/tests/delegatedProperty/inference/delegateExpressionAsLambda.fir.kt index 2f1e994bd1e..93568f554b6 100644 --- a/compiler/testData/diagnostics/tests/delegatedProperty/inference/delegateExpressionAsLambda.fir.kt +++ b/compiler/testData/diagnostics/tests/delegatedProperty/inference/delegateExpressionAsLambda.fir.kt @@ -7,7 +7,7 @@ fun test(i: Int) { createSample(i) { it.toString() } } - takeSample(bad) + takeSample(bad) } fun myLazyDelegate(i: () -> T): LazyDelegate = LazyDelegate(i()) @@ -19,4 +19,4 @@ class LazyDelegate(val v: T) { class Sample fun takeSample(g: Sample) {} -fun createSample(i: T, a: (T) -> S): Sample = TODO() \ No newline at end of file +fun createSample(i: T, a: (T) -> S): Sample = TODO()