diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index 607917ffe52..eab2c46ec0e 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -31624,6 +31624,22 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti } } + @Nested + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/builderInference") + @TestDataPath("$PROJECT_ROOT") + public class BuilderInference extends AbstractFirDiagnosticTest { + @Test + public void testAllFilesPresentInBuilderInference() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/builderInference"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); + } + + @Test + @TestMetadata("completeIrrelevantCalls.kt") + public void testCompleteIrrelevantCalls() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/completeIrrelevantCalls.kt"); + } + } + @Nested @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/builtins") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt index bb3b6eb744b..25753813f69 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt @@ -239,14 +239,13 @@ internal object CheckLowPriorityInOverloadResolution : CheckerStage() { } internal object PostponedVariablesInitializerResolutionStage : ResolutionStage() { - private val BUILDER_INFERENCE_CLASS_ID: ClassId = ClassId.fromString("kotlin/BuilderInference") override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) { val argumentMapping = candidate.argumentMapping ?: return // TODO: convert type argument mapping to map [FirTypeParameterSymbol, FirTypedProjection?] if (candidate.typeArgumentMapping is TypeArgumentMapping.Mapped) return for (parameter in argumentMapping.values) { - if (!parameter.hasBuilderInferenceMarker()) continue + if (!parameter.hasBuilderInferenceAnnotation()) continue val type = parameter.returnTypeRef.coneType val receiverType = type.receiverType(callInfo.session) ?: continue @@ -263,8 +262,4 @@ internal object PostponedVariablesInitializerResolutionStage : ResolutionStage() } } } - - private fun FirValueParameter.hasBuilderInferenceMarker(): Boolean { - return this.hasAnnotation(BUILDER_INFERENCE_CLASS_ID) - } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirBuilderInferenceSession.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirBuilderInferenceSession.kt index 11ca5949b30..2ac113e844a 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirBuilderInferenceSession.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirBuilderInferenceSession.kt @@ -6,6 +6,8 @@ package org.jetbrains.kotlin.fir.resolve.inference import org.jetbrains.kotlin.fir.FirElement +import org.jetbrains.kotlin.fir.declarations.FirAnnotatedDeclaration +import org.jetbrains.kotlin.fir.declarations.hasAnnotation import org.jetbrains.kotlin.fir.expressions.FirArgumentList import org.jetbrains.kotlin.fir.expressions.FirResolvable import org.jetbrains.kotlin.fir.expressions.FirStatement @@ -13,13 +15,18 @@ import org.jetbrains.kotlin.fir.resolve.calls.Candidate import org.jetbrains.kotlin.fir.resolve.calls.ResolutionContext import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.types.* -import org.jetbrains.kotlin.fir.visitors.* +import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult +import org.jetbrains.kotlin.fir.visitors.FirDefaultTransformer +import org.jetbrains.kotlin.fir.visitors.compose +import org.jetbrains.kotlin.fir.visitors.transformSingle +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.resolve.calls.inference.buildAbstractResultingSubstitutor import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionMode import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage import org.jetbrains.kotlin.resolve.calls.inference.model.CoroutinePosition import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl +import org.jetbrains.kotlin.resolve.descriptorUtil.BUILDER_INFERENCE_ANNOTATION_FQ_NAME import org.jetbrains.kotlin.types.model.TypeConstructorMarker class FirBuilderInferenceSession( @@ -33,6 +40,8 @@ class FirBuilderInferenceSession( val system = candidate.system if (system.hasContradiction) return true + if (!candidate.isSuitableForBuilderInference()) return true + val storage = system.getBuilder().currentStorage() @@ -45,6 +54,23 @@ class FirBuilderInferenceSession( } } + private fun Candidate.isSuitableForBuilderInference(): Boolean { + val extensionReceiver = extensionReceiverValue + val dispatchReceiver = dispatchReceiverValue + return when { + extensionReceiver == null && dispatchReceiver == null -> false + dispatchReceiver?.type?.containsStubType() == true -> true + extensionReceiver?.type?.containsStubType() == true -> symbol.fir.hasBuilderInferenceAnnotation() + else -> false + } + } + + private fun ConeKotlinType.containsStubType(): Boolean { + return this.contains { + it is ConeStubType + } + } + private fun FirStatement.hasPostponed(): Boolean { var result = false processAllContainingCallCandidates(processBlocks = false) { @@ -243,3 +269,8 @@ class FirStubTypeTransformer( override fun transformArgumentList(argumentList: FirArgumentList, data: Nothing?): CompositeTransformResult = argumentList.transformArguments(this, data).compose() } + +private val BUILDER_INFERENCE_ANNOTATION_CLASS_ID = ClassId.topLevel(BUILDER_INFERENCE_ANNOTATION_FQ_NAME) + +fun FirElement.hasBuilderInferenceAnnotation(): Boolean = + (this as? FirAnnotatedDeclaration)?.hasAnnotation(BUILDER_INFERENCE_ANNOTATION_CLASS_ID) == true diff --git a/compiler/testData/diagnostics/testsWithStdLib/builderInference/completeIrrelevantCalls.kt b/compiler/testData/diagnostics/testsWithStdLib/builderInference/completeIrrelevantCalls.kt new file mode 100644 index 00000000000..61e430dd75f --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/builderInference/completeIrrelevantCalls.kt @@ -0,0 +1,16 @@ +// FIR_IDENTICAL +// SKIP_TXT + +class A { + lateinit var m: Map + + @ExperimentalStdlibApi + fun foo(xs: Collection>) { + m = buildMap { + // flatMap calls might be completed on early phase + for (x in xs.flatMap { it.toList() }) { + put(x, x.length) + } + } + } +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/kt41308.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/kt41308.fir.kt deleted file mode 100644 index f31747fa9b1..00000000000 --- a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/kt41308.fir.kt +++ /dev/null @@ -1,9 +0,0 @@ -// ISSUE: KT-41308 - -fun main() { - sequence { - val list: List? = null - val outputList = ")!>list ?: listOf() - yieldAll(outputList) - } -} diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/kt41308.kt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/kt41308.kt index 14e081cacc7..f866bcfc5eb 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/kt41308.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/kt41308.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // ISSUE: KT-41308 fun main() { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index 4b144e033e6..369b623008a 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -31720,6 +31720,22 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { } } + @Nested + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/builderInference") + @TestDataPath("$PROJECT_ROOT") + public class BuilderInference extends AbstractDiagnosticTest { + @Test + public void testAllFilesPresentInBuilderInference() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/builderInference"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); + } + + @Test + @TestMetadata("completeIrrelevantCalls.kt") + public void testCompleteIrrelevantCalls() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/completeIrrelevantCalls.kt"); + } + } + @Nested @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/builtins") @TestDataPath("$PROJECT_ROOT")