Capture flexible intersection types properly: take into account both bounds and use the same captured arguments for them
^KT-41693 Fixed
This commit is contained in:
Generated
+5
@@ -12692,6 +12692,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
runTest("compiler/testData/codegen/box/inference/referenceToCatchParameterFromLambdaExpression.kt");
|
runTest("compiler/testData/codegen/box/inference/referenceToCatchParameterFromLambdaExpression.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("subtypingOfIntersectionIltInsideFlexible.kt")
|
||||||
|
public void testSubtypingOfIntersectionIltInsideFlexible() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/inference/subtypingOfIntersectionIltInsideFlexible.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("unsafeVarianceCodegen.kt")
|
@TestMetadata("unsafeVarianceCodegen.kt")
|
||||||
public void testUnsafeVarianceCodegen() throws Exception {
|
public void testUnsafeVarianceCodegen() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt");
|
runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt");
|
||||||
|
|||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
// IGNORE_BACKEND: JS
|
||||||
|
// IGNORE_BACKEND: JS_IR
|
||||||
|
|
||||||
|
// FILE: Bar.java
|
||||||
|
public class Bar {
|
||||||
|
public static String bar() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: main.kt
|
||||||
|
fun foo(): Any? {
|
||||||
|
return if (true) {
|
||||||
|
if (true) {
|
||||||
|
Bar.bar()
|
||||||
|
} else {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String? {
|
||||||
|
foo()
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+5
@@ -13917,6 +13917,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
runTest("compiler/testData/codegen/box/inference/referenceToCatchParameterFromLambdaExpression.kt");
|
runTest("compiler/testData/codegen/box/inference/referenceToCatchParameterFromLambdaExpression.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("subtypingOfIntersectionIltInsideFlexible.kt")
|
||||||
|
public void testSubtypingOfIntersectionIltInsideFlexible() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/inference/subtypingOfIntersectionIltInsideFlexible.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("unsafeVarianceCodegen.kt")
|
@TestMetadata("unsafeVarianceCodegen.kt")
|
||||||
public void testUnsafeVarianceCodegen() throws Exception {
|
public void testUnsafeVarianceCodegen() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt");
|
runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt");
|
||||||
|
|||||||
+5
@@ -13917,6 +13917,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTest("compiler/testData/codegen/box/inference/referenceToCatchParameterFromLambdaExpression.kt");
|
runTest("compiler/testData/codegen/box/inference/referenceToCatchParameterFromLambdaExpression.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("subtypingOfIntersectionIltInsideFlexible.kt")
|
||||||
|
public void testSubtypingOfIntersectionIltInsideFlexible() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/inference/subtypingOfIntersectionIltInsideFlexible.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("unsafeVarianceCodegen.kt")
|
@TestMetadata("unsafeVarianceCodegen.kt")
|
||||||
public void testUnsafeVarianceCodegen() throws Exception {
|
public void testUnsafeVarianceCodegen() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt");
|
runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt");
|
||||||
|
|||||||
+5
@@ -12692,6 +12692,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/inference/referenceToCatchParameterFromLambdaExpression.kt");
|
runTest("compiler/testData/codegen/box/inference/referenceToCatchParameterFromLambdaExpression.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("subtypingOfIntersectionIltInsideFlexible.kt")
|
||||||
|
public void testSubtypingOfIntersectionIltInsideFlexible() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/inference/subtypingOfIntersectionIltInsideFlexible.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("unsafeVarianceCodegen.kt")
|
@TestMetadata("unsafeVarianceCodegen.kt")
|
||||||
public void testUnsafeVarianceCodegen() throws Exception {
|
public void testUnsafeVarianceCodegen() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt");
|
runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt");
|
||||||
|
|||||||
@@ -36,24 +36,57 @@ fun prepareArgumentTypeRegardingCaptureTypes(argumentType: UnwrappedType): Unwra
|
|||||||
|
|
||||||
fun captureFromExpression(type: UnwrappedType): UnwrappedType? {
|
fun captureFromExpression(type: UnwrappedType): UnwrappedType? {
|
||||||
val typeConstructor = type.constructor
|
val typeConstructor = type.constructor
|
||||||
if (typeConstructor is IntersectionTypeConstructor) {
|
|
||||||
var changed = false
|
if (typeConstructor !is IntersectionTypeConstructor) {
|
||||||
val capturedSupertypes = typeConstructor.supertypes.map { supertype ->
|
return captureFromArguments(type, CaptureStatus.FROM_EXPRESSION)
|
||||||
val unwrapped = supertype.unwrap()
|
}
|
||||||
captureFromExpression(unwrapped)?.apply { changed = true } ?: unwrapped
|
|
||||||
|
/*
|
||||||
|
* We capture intersection types in two stages:
|
||||||
|
* capture type arguments for each component and replace it in the original type after that.
|
||||||
|
* This is to substitute captured types into flexible types properly:
|
||||||
|
* we should have the same captured types both for lower bound and for upper one.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* The original type: ({Comparable<*> & java.io.Serializable}..{Comparable<*>? & java.io.Serializable?})
|
||||||
|
* Result of capturing arguments by components: [[CapturedType(*)], null]
|
||||||
|
* The resulting type: ({Comparable<CapturedType(*)> & java.io.Serializable}..{Comparable<CapturedType(*)>? & java.io.Serializable?})
|
||||||
|
*/
|
||||||
|
val capturedArgumentsByComponents = captureArgumentsForIntersectionType(typeConstructor) ?: return null
|
||||||
|
|
||||||
|
fun replaceArgumentsByComponents(typeToReplace: UnwrappedType) =
|
||||||
|
typeToReplace.constructor.supertypes.mapIndexed { i, componentType ->
|
||||||
|
val capturedArguments = capturedArgumentsByComponents[i] ?: return@mapIndexed componentType.asSimpleType()
|
||||||
|
componentType.unwrap().replaceArguments(capturedArguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!changed) return null
|
return if (type is FlexibleType) {
|
||||||
|
val lowerIntersectedType =
|
||||||
|
intersectTypes(replaceArgumentsByComponents(type.lowerBound)).makeNullableAsSpecified(type.lowerBound.isMarkedNullable)
|
||||||
|
val upperIntersectedType =
|
||||||
|
intersectTypes(replaceArgumentsByComponents(type.upperBound)).makeNullableAsSpecified(type.upperBound.isMarkedNullable)
|
||||||
|
|
||||||
return intersectTypes(capturedSupertypes).makeNullableAsSpecified(type.isMarkedNullable)
|
KotlinTypeFactory.flexibleType(lowerIntersectedType, upperIntersectedType)
|
||||||
|
} else {
|
||||||
|
intersectTypes(replaceArgumentsByComponents(type)).makeNullableAsSpecified(type.isMarkedNullable)
|
||||||
}
|
}
|
||||||
return captureFromArguments(type, CaptureStatus.FROM_EXPRESSION)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// this function suppose that input type is simple classifier type
|
// this function suppose that input type is simple classifier type
|
||||||
internal fun captureFromArguments(type: SimpleType, status: CaptureStatus) =
|
internal fun captureFromArguments(type: SimpleType, status: CaptureStatus) =
|
||||||
captureArguments(type, status)?.let { type.replaceArguments(it) }
|
captureArguments(type, status)?.let { type.replaceArguments(it) }
|
||||||
|
|
||||||
|
private fun captureArgumentsForIntersectionType(typeConstructor: TypeConstructor): List<List<TypeProjection>?>? {
|
||||||
|
var changed = false
|
||||||
|
val capturedArgumentsByComponents = typeConstructor.supertypes.map { supertype ->
|
||||||
|
captureArguments(supertype.unwrap(), CaptureStatus.FROM_EXPRESSION)?.apply { changed = true }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!changed) return null
|
||||||
|
|
||||||
|
return capturedArgumentsByComponents
|
||||||
|
}
|
||||||
|
|
||||||
private fun captureFromArguments(type: UnwrappedType, status: CaptureStatus): UnwrappedType? {
|
private fun captureFromArguments(type: UnwrappedType, status: CaptureStatus): UnwrappedType? {
|
||||||
val capturedArguments = captureArguments(type, status) ?: return null
|
val capturedArguments = captureArguments(type, status) ?: return null
|
||||||
|
|
||||||
|
|||||||
Generated
+5
@@ -10862,6 +10862,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
|
|||||||
runTest("compiler/testData/codegen/box/inference/referenceToCatchParameterFromLambdaExpression.kt");
|
runTest("compiler/testData/codegen/box/inference/referenceToCatchParameterFromLambdaExpression.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("subtypingOfIntersectionIltInsideFlexible.kt")
|
||||||
|
public void testSubtypingOfIntersectionIltInsideFlexible() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/inference/subtypingOfIntersectionIltInsideFlexible.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("unsafeVarianceCodegen.kt")
|
@TestMetadata("unsafeVarianceCodegen.kt")
|
||||||
public void testUnsafeVarianceCodegen() throws Exception {
|
public void testUnsafeVarianceCodegen() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt");
|
runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt");
|
||||||
|
|||||||
Generated
+5
@@ -10862,6 +10862,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/inference/referenceToCatchParameterFromLambdaExpression.kt");
|
runTest("compiler/testData/codegen/box/inference/referenceToCatchParameterFromLambdaExpression.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("subtypingOfIntersectionIltInsideFlexible.kt")
|
||||||
|
public void testSubtypingOfIntersectionIltInsideFlexible() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/inference/subtypingOfIntersectionIltInsideFlexible.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("unsafeVarianceCodegen.kt")
|
@TestMetadata("unsafeVarianceCodegen.kt")
|
||||||
public void testUnsafeVarianceCodegen() throws Exception {
|
public void testUnsafeVarianceCodegen() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt");
|
runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt");
|
||||||
|
|||||||
+5
@@ -10927,6 +10927,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/inference/referenceToCatchParameterFromLambdaExpression.kt");
|
runTest("compiler/testData/codegen/box/inference/referenceToCatchParameterFromLambdaExpression.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("subtypingOfIntersectionIltInsideFlexible.kt")
|
||||||
|
public void testSubtypingOfIntersectionIltInsideFlexible() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/inference/subtypingOfIntersectionIltInsideFlexible.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("unsafeVarianceCodegen.kt")
|
@TestMetadata("unsafeVarianceCodegen.kt")
|
||||||
public void testUnsafeVarianceCodegen() throws Exception {
|
public void testUnsafeVarianceCodegen() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt");
|
runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user