diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt index b751a73216b..7f95a98921b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt @@ -20,7 +20,6 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.getReturnTypeFromFunctionType import org.jetbrains.kotlin.builtins.getValueParameterTypesFromFunctionType import org.jetbrains.kotlin.builtins.isFunctionType -import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.psi.* @@ -75,10 +74,10 @@ class CallCompleter( // it's completed when the outer (variable as function call) is completed if (!isInvokeCallOnVariable(context.call)) { val temporaryTrace = TemporaryBindingTrace.create(context.trace, "Trace to complete a resulting call") + val contextWithTemporaryTrace = context.replaceBindingTrace(temporaryTrace) - completeResolvedCallAndArguments(resolvedCall, results, context.replaceBindingTrace(temporaryTrace), tracing) - - completeAllCandidates(context, results) + completeResolvedCallAndArguments(resolvedCall, results, contextWithTemporaryTrace, tracing) + completeAllCandidates(contextWithTemporaryTrace, results) temporaryTrace.commit() } @@ -120,10 +119,10 @@ class CallCompleter( results.resultingCalls }) as Collection> + val temporaryBindingTrace = TemporaryBindingTrace.create(context.trace, "Trace to complete a candidate that is not a resulting call") candidates.filterNot { resolvedCall -> resolvedCall.isCompleted }.forEach { resolvedCall -> - val temporaryBindingTrace = TemporaryBindingTrace.create(context.trace, "Trace to complete a candidate that is not a resulting call") completeResolvedCallAndArguments(resolvedCall, results, context.replaceBindingTrace(temporaryBindingTrace), TracingStrategy.EMPTY) } } diff --git a/compiler/testData/diagnostics/tests/resolve/nestedCalls/manyInapplicableCandidatesWithLambdas.kt b/compiler/testData/diagnostics/tests/resolve/nestedCalls/manyInapplicableCandidatesWithLambdas.kt new file mode 100644 index 00000000000..d04bdf6472d --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/nestedCalls/manyInapplicableCandidatesWithLambdas.kt @@ -0,0 +1,53 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +class A +class B +class C +class D + +fun A.bar(x: Int = 0) = "" +fun A.bar(x: Int = 0, y: D.() -> Unit) = "" + +fun B.bar(x: Int = 0) = "" +fun B.bar(x: Int = 0, y: D.() -> Unit) = "" + +fun C.bar(x: Int = 0) = "" +fun C.bar(x: Int = 0, y: D.() -> Unit) = "" + +class E { + fun foo() { + // `bar` calls are inapplicable since both E nor D aren't proper receivers + // But prior to this change, every lambda was analyzed repeatedly for every candidate + // Thus, the resulting time was exponential + bar { + bar { + bar { + bar { + bar { + bar { + bar { + bar { + bar { + bar { + bar { + bar { + bar { + bar { + + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } +} + diff --git a/compiler/testData/diagnostics/tests/resolve/nestedCalls/manyInapplicableCandidatesWithLambdas.txt b/compiler/testData/diagnostics/tests/resolve/nestedCalls/manyInapplicableCandidatesWithLambdas.txt new file mode 100644 index 00000000000..00ffa8fd140 --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/nestedCalls/manyInapplicableCandidatesWithLambdas.txt @@ -0,0 +1,44 @@ +package + +public fun A.bar(/*0*/ x: kotlin.Int = ...): kotlin.String +public fun A.bar(/*0*/ x: kotlin.Int = ..., /*1*/ y: D.() -> kotlin.Unit): kotlin.String +public fun B.bar(/*0*/ x: kotlin.Int = ...): kotlin.String +public fun B.bar(/*0*/ x: kotlin.Int = ..., /*1*/ y: D.() -> kotlin.Unit): kotlin.String +public fun C.bar(/*0*/ x: kotlin.Int = ...): kotlin.String +public fun C.bar(/*0*/ x: kotlin.Int = ..., /*1*/ y: D.() -> kotlin.Unit): kotlin.String + +public final class A { + public constructor A() + 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 B { + public constructor B() + 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 C { + public constructor C() + 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 D { + public constructor D() + 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 E { + public constructor E() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun foo(): kotlin.Unit + 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/testsWithStdLib/hugeUnresolvedKotlinxHtml.kt b/compiler/testData/diagnostics/testsWithStdLib/hugeUnresolvedKotlinxHtml.kt new file mode 100644 index 00000000000..71af45128d5 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/hugeUnresolvedKotlinxHtml.kt @@ -0,0 +1,60 @@ +class A { + fun bar() { + div { + div { + div { + div { + div { + div { + div { + div { + div { + div { + div { + div { + div { + div { + div { + div { + div { + div { + div { + div { + div { + div { + div { + +(foo ?: "") + +(foo ?: "") + +(foo ?: "") + +(foo ?: "") + +(foo ?: "") + +(foo ?: "") + +(foo ?: "") + +(foo ?: "") + +(foo ?: "") + } + } + } + } + } + } + } + } + } + } + } + + } + } + } + } + } + } + } + } + } + } + } + } + } +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/hugeUnresolvedKotlinxHtml.txt b/compiler/testData/diagnostics/testsWithStdLib/hugeUnresolvedKotlinxHtml.txt new file mode 100644 index 00000000000..fca4481c35d --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/hugeUnresolvedKotlinxHtml.txt @@ -0,0 +1,9 @@ +package + +public final class A { + public constructor A() + public final fun bar(): 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 d8a237bb2b1..48238a5d028 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -18123,6 +18123,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("manyInapplicableCandidatesWithLambdas.kt") + public void testManyInapplicableCandidatesWithLambdas() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/resolve/nestedCalls/manyInapplicableCandidatesWithLambdas.kt"); + doTest(fileName); + } + @TestMetadata("twoTypeParameters.kt") public void testTwoTypeParameters() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/resolve/nestedCalls/twoTypeParameters.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java index 6166d62dfbb..42de2143933 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java @@ -78,6 +78,12 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW doTest(fileName); } + @TestMetadata("hugeUnresolvedKotlinxHtml.kt") + public void testHugeUnresolvedKotlinxHtml() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/hugeUnresolvedKotlinxHtml.kt"); + doTest(fileName); + } + @TestMetadata("ifElseJavaList.kt") public void testIfElseJavaList() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/ifElseJavaList.kt");