[FIR] Only don't approximate nested captured arguments if they have recursive supertypes

This fixes a compiler crash
IllegalStateException: Captured type for incorporation shouldn't escape
from incorporation

The crash occurs when a captured type with status FOR_INCORPORATION
is two layers deep inside a captured type with status FROM_EXPRESSION.
We first check if approximation is required for the most outer captured
type in AbstractTypeApproximator.approximateCapturedType.
Then we encounter the second captured type with status FROM_EXPRESSION
in AbstractTypeApproximator.approximateParametrizedType.
At this point, we stop checking and miss the third captured type with
status FOR_INCORPORATION.

Unfortunately, we can't check recursively if nested captured types
need to be approximated because of types with recursive super types
(the original reason why the extra check was introduced).
That's why we restrict the second check to types with recursive
super types, effectively restoring the previous behavior for all other
types.

#KT-65050 Fixed
This commit is contained in:
Kirill Rakhman
2024-01-17 17:18:11 +01:00
committed by Space Team
parent 7587f73846
commit 582dd1d3c0
7 changed files with 54 additions and 1 deletions
@@ -17899,6 +17899,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturedFlexibleIntersectionTypesWithDifferentConstructors.kt");
}
@Test
@TestMetadata("capturedForIncorporationEscapes.kt")
public void testCapturedForIncorporationEscapes() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturedForIncorporationEscapes.kt");
}
@Test
@TestMetadata("capturedInTypeInference.kt")
public void testCapturedInTypeInference() throws Exception {
@@ -17899,6 +17899,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturedFlexibleIntersectionTypesWithDifferentConstructors.kt");
}
@Test
@TestMetadata("capturedForIncorporationEscapes.kt")
public void testCapturedForIncorporationEscapes() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturedForIncorporationEscapes.kt");
}
@Test
@TestMetadata("capturedInTypeInference.kt")
public void testCapturedInTypeInference() throws Exception {
@@ -17893,6 +17893,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturedFlexibleIntersectionTypesWithDifferentConstructors.kt");
}
@Test
@TestMetadata("capturedForIncorporationEscapes.kt")
public void testCapturedForIncorporationEscapes() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturedForIncorporationEscapes.kt");
}
@Test
@TestMetadata("capturedInTypeInference.kt")
public void testCapturedInTypeInference() throws Exception {
@@ -17899,6 +17899,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturedFlexibleIntersectionTypesWithDifferentConstructors.kt");
}
@Test
@TestMetadata("capturedForIncorporationEscapes.kt")
public void testCapturedForIncorporationEscapes() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturedForIncorporationEscapes.kt");
}
@Test
@TestMetadata("capturedInTypeInference.kt")
public void testCapturedInTypeInference() throws Exception {
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.types
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator.commonSuperType
import org.jetbrains.kotlin.resolve.calls.inference.hasRecursiveTypeParametersWithGivenSelfType
import org.jetbrains.kotlin.types.model.*
import org.jetbrains.kotlin.utils.addToStdlib.runIf
import java.util.concurrent.ConcurrentHashMap
@@ -481,7 +482,11 @@ abstract class AbstractTypeApproximator(
// In approximateCapturedType, we check if the super/subtypes of captured types need approximation even if captured types
// themselves don't need approximation, and will land here.
// To support this case, we also don't want to approximate captured types here if the configuration says so.
if (capturedType != null && isK2 && !conf.capturedType(ctx, capturedType)) {
if (capturedType != null &&
isK2 &&
!conf.capturedType(ctx, capturedType) &&
ctx.hasRecursiveTypeParametersWithGivenSelfType(capturedType.typeConstructor())
) {
continue@loop
}
@@ -0,0 +1,18 @@
// FIR_IDENTICAL
// ISSUE: KT-65050
interface HttpResponse<T>
class GitLabMergeRequestShortRestDTO
fun loadMergeRequests(): HttpResponse<out List<GitLabMergeRequestShortRestDTO>> = TODO()
inline fun <reified T> loadList(): HttpResponse<out List<T>> = TODO()
fun loadMergeRequests(boolean: Boolean) {
val response = if (boolean) {
loadMergeRequests()
} else {
loadList()
}
}
@@ -17899,6 +17899,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturedFlexibleIntersectionTypesWithDifferentConstructors.kt");
}
@Test
@TestMetadata("capturedForIncorporationEscapes.kt")
public void testCapturedForIncorporationEscapes() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturedForIncorporationEscapes.kt");
}
@Test
@TestMetadata("capturedInTypeInference.kt")
public void testCapturedInTypeInference() throws Exception {