AA FE1.0: Fix StackOverflowError during resolution to a function w/ recursive type parameter
^KT-55825 Fixed
diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/base/Kt1DescUtils.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/base/Kt1DescUtils.kt
index ce443aa..1df129d 100644
--- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/base/Kt1DescUtils.kt
+++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/base/Kt1DescUtils.kt
@@ -231,7 +231,12 @@
declarationDescriptor !in allowedTypeParameterDescriptors ||
declarationDescriptor.upperBounds.any { it.hasReferenceOtherThan(allowedTypeParameterDescriptors) }
}
- else -> arguments.any { it.type.hasReferenceOtherThan(allowedTypeParameterDescriptors) }
+ else -> arguments.any { typeProjection ->
+ // A star projection type (lazily) built by type parameter will be yet another type with a star projection,
+ // resulting in stack overflow if we keep checking allowed type parameter descriptors
+ !typeProjection.isStarProjection &&
+ typeProjection.type.hasReferenceOtherThan(allowedTypeParameterDescriptors)
+ }
}
}
diff --git a/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/components/callResolver/Fe10IdeNormalAnalysisSourceModuleResolveCallTestGenerated.java b/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/components/callResolver/Fe10IdeNormalAnalysisSourceModuleResolveCallTestGenerated.java
index 3246ca1..cad7e1c 100644
--- a/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/components/callResolver/Fe10IdeNormalAnalysisSourceModuleResolveCallTestGenerated.java
+++ b/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/components/callResolver/Fe10IdeNormalAnalysisSourceModuleResolveCallTestGenerated.java
@@ -701,6 +701,12 @@
}
@Test
+ @TestMetadata("recursiveTypeParameter.kt")
+ public void testRecursiveTypeParameter() throws Exception {
+ runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/recursiveTypeParameter.kt");
+ }
+
+ @Test
@TestMetadata("resolveCallInSuperConstructorParam.kt")
public void testResolveCallInSuperConstructorParam() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/resolveCallInSuperConstructorParam.kt");
diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/callResolver/FirIdeNormalAnalysisSourceModuleResolveCallTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/callResolver/FirIdeNormalAnalysisSourceModuleResolveCallTestGenerated.java
index 3c5fae1..b1013ce 100644
--- a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/callResolver/FirIdeNormalAnalysisSourceModuleResolveCallTestGenerated.java
+++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/callResolver/FirIdeNormalAnalysisSourceModuleResolveCallTestGenerated.java
@@ -701,6 +701,12 @@
}
@Test
+ @TestMetadata("recursiveTypeParameter.kt")
+ public void testRecursiveTypeParameter() throws Exception {
+ runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/recursiveTypeParameter.kt");
+ }
+
+ @Test
@TestMetadata("resolveCallInSuperConstructorParam.kt")
public void testResolveCallInSuperConstructorParam() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/resolveCallInSuperConstructorParam.kt");
diff --git a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/callResolver/FirStandaloneNormalAnalysisSourceModuleResolveCallTestGenerated.java b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/callResolver/FirStandaloneNormalAnalysisSourceModuleResolveCallTestGenerated.java
index 93ceecb..9623569 100644
--- a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/callResolver/FirStandaloneNormalAnalysisSourceModuleResolveCallTestGenerated.java
+++ b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/callResolver/FirStandaloneNormalAnalysisSourceModuleResolveCallTestGenerated.java
@@ -701,6 +701,12 @@
}
@Test
+ @TestMetadata("recursiveTypeParameter.kt")
+ public void testRecursiveTypeParameter() throws Exception {
+ runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/recursiveTypeParameter.kt");
+ }
+
+ @Test
@TestMetadata("resolveCallInSuperConstructorParam.kt")
public void testResolveCallInSuperConstructorParam() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/resolveCallInSuperConstructorParam.kt");
diff --git a/analysis/analysis-api/testData/components/callResolver/resolveCall/recursiveTypeParameter.descriptors.txt b/analysis/analysis-api/testData/components/callResolver/resolveCall/recursiveTypeParameter.descriptors.txt
new file mode 100644
index 0000000..5391e0e
--- /dev/null
+++ b/analysis/analysis-api/testData/components/callResolver/resolveCall/recursiveTypeParameter.descriptors.txt
@@ -0,0 +1,49 @@
+KtSuccessCallInfo:
+ call = KtSimpleFunctionCall:
+ isImplicitInvoke = false
+ partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
+ dispatchReceiver = KtImplicitReceiverValue:
+ symbol = KtNamedClassOrObjectSymbol:
+ annotationsList: []
+ classIdIfNonLocal: RunnerModule
+ classKind: CLASS
+ companionObject: null
+ contextReceivers: []
+ isData: false
+ isExternal: false
+ isFun: false
+ isInline: false
+ isInner: false
+ modality: FINAL
+ name: RunnerModule
+ origin: SOURCE
+ superTypes: [
+ AbstractModule
+ ]
+ symbolKind: TOP_LEVEL
+ typeParameters: []
+ visibility: Public
+ type = RunnerModule
+ extensionReceiver = null
+ signature = KtFunctionLikeSignature:
+ receiverType = null
+ returnType = kotlin.Unit
+ symbol = /AbstractModule.install(<dispatch receiver>: AbstractModule, builder: AbstractModule.Builder<*>!): kotlin.Unit
+ valueParameters = [
+ KtVariableLikeSignature:
+ name = builder
+ receiverType = null
+ returnType = AbstractModule.Builder<*>!
+ symbol = builder: AbstractModule.Builder<*>!
+ callableIdIfNonLocal = null
+ ]
+ callableIdIfNonLocal = /AbstractModule.install
+ typeArgumentsMapping = {}
+ argumentMapping = {
+ CoroutineModule.builder() -> (KtVariableLikeSignature:
+ name = builder
+ receiverType = null
+ returnType = AbstractModule.Builder<*>!
+ symbol = builder: AbstractModule.Builder<*>!
+ callableIdIfNonLocal = null)
+ }
diff --git a/analysis/analysis-api/testData/components/callResolver/resolveCall/recursiveTypeParameter.kt b/analysis/analysis-api/testData/components/callResolver/resolveCall/recursiveTypeParameter.kt
new file mode 100644
index 0000000..525cf8e
--- /dev/null
+++ b/analysis/analysis-api/testData/components/callResolver/resolveCall/recursiveTypeParameter.kt
@@ -0,0 +1,39 @@
+// FILE: RunnerModule.kt
+
+class RunnerModule : AbstractModule() {
+ fun configure() {
+ <expr>install(CoroutineModule.builder())</expr>
+ }
+}
+
+// FILE: Module.java
+
+public interface Module {
+ public interface Builder {
+ Module build();
+ }
+}
+
+// FILE: AbstractModule.java
+
+public abstract class AbstractModule {
+ public abstract static class Builder<B extends Builder<B>> implements Module.Builder {
+ protected abstract B self();
+ public abstract Module build();
+ }
+
+ protected void install(Builder<?> builder) {}
+}
+
+// FILE: CoroutineModule.kt
+
+class CoroutineModule : AbstractModule() {
+ class Builder : AbstractModule.Builder<Builder>() {
+ protected override fun self(): Builder = this
+ override fun build(): Module = CoroutineModule()
+ }
+
+ companion object {
+ fun builder(): Builder = Builder()
+ }
+}
diff --git a/analysis/analysis-api/testData/components/callResolver/resolveCall/recursiveTypeParameter.txt b/analysis/analysis-api/testData/components/callResolver/resolveCall/recursiveTypeParameter.txt
new file mode 100644
index 0000000..8eae8b0
--- /dev/null
+++ b/analysis/analysis-api/testData/components/callResolver/resolveCall/recursiveTypeParameter.txt
@@ -0,0 +1,49 @@
+KtSuccessCallInfo:
+ call = KtSimpleFunctionCall:
+ isImplicitInvoke = false
+ partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
+ dispatchReceiver = KtImplicitReceiverValue:
+ symbol = KtNamedClassOrObjectSymbol:
+ annotationsList: []
+ classIdIfNonLocal: RunnerModule
+ classKind: CLASS
+ companionObject: null
+ contextReceivers: []
+ isData: false
+ isExternal: false
+ isFun: false
+ isInline: false
+ isInner: false
+ modality: FINAL
+ name: RunnerModule
+ origin: SOURCE
+ superTypes: [
+ AbstractModule
+ ]
+ symbolKind: TOP_LEVEL
+ typeParameters: []
+ visibility: Public
+ type = RunnerModule
+ extensionReceiver = null
+ signature = KtFunctionLikeSignature:
+ receiverType = null
+ returnType = kotlin.Unit
+ symbol = /AbstractModule.install(<dispatch receiver>: AbstractModule, builder: ft<AbstractModule.Builder<*>, AbstractModule.Builder<*>?>): kotlin.Unit
+ valueParameters = [
+ KtVariableLikeSignature:
+ name = builder
+ receiverType = null
+ returnType = ft<AbstractModule.Builder<*>, AbstractModule.Builder<*>?>
+ symbol = builder: ft<AbstractModule.Builder<*>, AbstractModule.Builder<*>?>
+ callableIdIfNonLocal = null
+ ]
+ callableIdIfNonLocal = /AbstractModule.install
+ typeArgumentsMapping = {}
+ argumentMapping = {
+ CoroutineModule.builder() -> (KtVariableLikeSignature:
+ name = builder
+ receiverType = null
+ returnType = ft<AbstractModule.Builder<*>, AbstractModule.Builder<*>?>
+ symbol = builder: ft<AbstractModule.Builder<*>, AbstractModule.Builder<*>?>
+ callableIdIfNonLocal = null)
+ }