[FIR] Don't capture flexible types that only have projections in one bound
This fixes a false positive NEW_INFERENCE_ERROR. See the code comment for the rationale. #KT-63982 Fixed
This commit is contained in:
committed by
Space Team
parent
eaa93b2582
commit
476a0b6783
+6
@@ -16430,6 +16430,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/kt62609.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/kt62609.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt63982.kt")
|
||||||
|
public void testKt63982() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/kt63982.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("lambdaArgumentWithLabel.kt")
|
@TestMetadata("lambdaArgumentWithLabel.kt")
|
||||||
public void testLambdaArgumentWithLabel() throws Exception {
|
public void testLambdaArgumentWithLabel() throws Exception {
|
||||||
|
|||||||
+6
@@ -16430,6 +16430,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/kt62609.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/kt62609.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt63982.kt")
|
||||||
|
public void testKt63982() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/kt63982.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("lambdaArgumentWithLabel.kt")
|
@TestMetadata("lambdaArgumentWithLabel.kt")
|
||||||
public void testLambdaArgumentWithLabel() throws Exception {
|
public void testLambdaArgumentWithLabel() throws Exception {
|
||||||
|
|||||||
+6
@@ -16424,6 +16424,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/kt62609.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/kt62609.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt63982.kt")
|
||||||
|
public void testKt63982() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/kt63982.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("lambdaArgumentWithLabel.kt")
|
@TestMetadata("lambdaArgumentWithLabel.kt")
|
||||||
public void testLambdaArgumentWithLabel() throws Exception {
|
public void testLambdaArgumentWithLabel() throws Exception {
|
||||||
|
|||||||
+6
@@ -16430,6 +16430,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/kt62609.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/kt62609.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt63982.kt")
|
||||||
|
public void testKt63982() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/kt63982.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("lambdaArgumentWithLabel.kt")
|
@TestMetadata("lambdaArgumentWithLabel.kt")
|
||||||
public void testLambdaArgumentWithLabel() throws Exception {
|
public void testLambdaArgumentWithLabel() throws Exception {
|
||||||
|
|||||||
@@ -533,32 +533,43 @@ internal fun ConeTypeContext.captureFromExpressionInternal(type: ConeKotlinType)
|
|||||||
fun findCorrespondingCapturedArgumentsForType(type: ConeKotlinType) =
|
fun findCorrespondingCapturedArgumentsForType(type: ConeKotlinType) =
|
||||||
capturedArgumentsByComponents.find { typeToCapture -> typeToCapture.isSuitableForType(type, this) }?.capturedArguments
|
capturedArgumentsByComponents.find { typeToCapture -> typeToCapture.isSuitableForType(type, this) }?.capturedArguments
|
||||||
|
|
||||||
fun replaceArgumentsWithCapturedArgumentsByIntersectionComponents(typeToReplace: ConeSimpleKotlinType): List<ConeKotlinType> {
|
fun replaceArgumentsWithCapturedArgumentsByIntersectionComponents(typeToReplace: ConeSimpleKotlinType): List<ConeKotlinType>? {
|
||||||
return if (typeToReplace is ConeIntersectionType) {
|
return if (typeToReplace is ConeIntersectionType) {
|
||||||
typeToReplace.intersectedTypes.map { componentType ->
|
typeToReplace.intersectedTypes.map { componentType ->
|
||||||
val capturedArguments = findCorrespondingCapturedArgumentsForType(componentType)
|
val capturedArguments = findCorrespondingCapturedArgumentsForType(componentType)
|
||||||
?: return@map componentType
|
?: return@map componentType
|
||||||
componentType.withArguments(capturedArguments)
|
componentType.withArguments(capturedArguments)
|
||||||
}
|
}.takeUnless { it == typeToReplace.intersectedTypes }
|
||||||
} else {
|
} else {
|
||||||
val capturedArguments = findCorrespondingCapturedArgumentsForType(typeToReplace)
|
val capturedArguments = findCorrespondingCapturedArgumentsForType(typeToReplace)
|
||||||
?: return listOf(typeToReplace)
|
?: return null
|
||||||
listOf(typeToReplace.withArguments(capturedArguments))
|
listOf(typeToReplace.withArguments(capturedArguments))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return when (type) {
|
return when (type) {
|
||||||
is ConeFlexibleType -> {
|
is ConeFlexibleType -> {
|
||||||
val lowerIntersectedType = intersectTypes(replaceArgumentsWithCapturedArgumentsByIntersectionComponents(type.lowerBound))
|
// Flexible types can either have projections in both bounds or just the upper bound (raw types and arrays).
|
||||||
.withNullability(ConeNullability.create(type.lowerBound.isMarkedNullable), this)
|
// Since the scope of flexible types is built from the lower bound, we don't gain any safety from only capturing the
|
||||||
val upperIntersectedType = intersectTypes(replaceArgumentsWithCapturedArgumentsByIntersectionComponents(type.upperBound))
|
// upper bound.
|
||||||
.withNullability(ConeNullability.create(type.upperBound.isMarkedNullable), this)
|
// At the same time, capturing of raw(-like) types leads to issues like KT-63982 or breaks tests like
|
||||||
|
// testData/codegen/box/reflection/typeOf/rawTypes_after.kt.
|
||||||
|
// Therefore, we return null if nothing was captured for either bound.
|
||||||
|
|
||||||
|
val lowerIntersectedType =
|
||||||
|
intersectTypes(replaceArgumentsWithCapturedArgumentsByIntersectionComponents(type.lowerBound) ?: return null)
|
||||||
|
.withNullability(ConeNullability.create(type.lowerBound.isMarkedNullable), this)
|
||||||
|
val upperIntersectedType =
|
||||||
|
intersectTypes(replaceArgumentsWithCapturedArgumentsByIntersectionComponents(type.upperBound) ?: return null)
|
||||||
|
.withNullability(ConeNullability.create(type.upperBound.isMarkedNullable), this)
|
||||||
|
|
||||||
ConeFlexibleType(lowerIntersectedType.coneLowerBoundIfFlexible(), upperIntersectedType.coneUpperBoundIfFlexible())
|
ConeFlexibleType(lowerIntersectedType.coneLowerBoundIfFlexible(), upperIntersectedType.coneUpperBoundIfFlexible())
|
||||||
}
|
}
|
||||||
|
|
||||||
is ConeSimpleKotlinType -> {
|
is ConeSimpleKotlinType -> {
|
||||||
intersectTypes(replaceArgumentsWithCapturedArgumentsByIntersectionComponents(type)).withNullability(type.isMarkedNullable) as ConeKotlinType
|
intersectTypes(
|
||||||
|
replaceArgumentsWithCapturedArgumentsByIntersectionComponents(type) ?: return null
|
||||||
|
).withNullability(type.isMarkedNullable) as ConeKotlinType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// ISSUE: KT-63982
|
||||||
|
// FIR_IDENTICAL
|
||||||
|
// DIAGNOSTICS: -DEBUG_INFO_SMARTCAST
|
||||||
|
|
||||||
|
// FILE: StubBasedPsiElement.java
|
||||||
|
public interface StubBasedPsiElement<Stub extends StubElement> extends PsiElement {
|
||||||
|
Stub getStub();
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: test.kt
|
||||||
|
interface PsiElement
|
||||||
|
interface JSCallExpression: PsiElement
|
||||||
|
interface StubElement<T : PsiElement>
|
||||||
|
|
||||||
|
fun test(child: PsiElement) {
|
||||||
|
if (child is JSCallExpression) {
|
||||||
|
val callStub = if (child is StubBasedPsiElement<*>) child.stub else null
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
+6
@@ -16430,6 +16430,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/kt62609.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/kt62609.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt63982.kt")
|
||||||
|
public void testKt63982() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/kt63982.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("lambdaArgumentWithLabel.kt")
|
@TestMetadata("lambdaArgumentWithLabel.kt")
|
||||||
public void testLambdaArgumentWithLabel() throws Exception {
|
public void testLambdaArgumentWithLabel() throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user