summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Petukhov <victor.petukhov@jetbrains.com>2022-06-17 15:01:53 +0200
committerVictor Petukhov <victor.petukhov@jetbrains.com>2022-06-17 17:38:53 +0200
commit52b0cd466a05b737040befb224068dc683f469c5 (patch)
tree6f847c8724332d9c77cdba19e54ad5280966d75c
parentc2da22da7704485af78b27dacbffdbd68948986e (diff)
downloadkotlin-52b0cd466a05b737040befb224068dc683f469c5.tar.gz
[FE 1.0] Build captured type's supertypes in an alternative way: use own projection type as a first supertype, then supertypes from the corresponding type parameter's upper bounds
The original case provoked forking a constraint system which isn't supported in K1 (K2 only). If the captured type is recursive, then type parameter's upper bounds may break subtyping due to substitution the current captured type again, into a recursive type parameter. Note that we already have special logic for recursive captured types. See `isTypeVariableAgainstStarProjectionForSelfType`. ^KT-52782 Fixed
-rw-r--r--analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java6
-rw-r--r--compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java6
-rw-r--r--compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java6
-rw-r--r--compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/NewTypeSubstitutor.kt6
-rw-r--r--compiler/testData/diagnostics/tests/inference/capturedTypes/kt52782.kt13
-rw-r--r--compiler/testData/diagnostics/tests/inference/capturedTypes/kt52782.txt18
-rw-r--r--compiler/testData/diagnostics/tests/inference/kt47316.kt2
-rw-r--r--compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java6
-rw-r--r--compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java10
-rw-r--r--core/descriptors/src/org/jetbrains/kotlin/types/checker/NewCapturedType.kt34
10 files changed, 88 insertions, 19 deletions
diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java
index 3c8fb41d3d0..1b765da4762 100644
--- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java
+++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java
@@ -14522,6 +14522,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
}
@Test
+ @TestMetadata("kt52782.kt")
+ public void testKt52782() throws Exception {
+ runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/kt52782.kt");
+ }
+
+ @Test
@TestMetadata("memberScopeOfCaptured.kt")
public void testMemberScopeOfCaptured() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/memberScopeOfCaptured.kt");
diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java
index e525cc6cb68..59802afddb7 100644
--- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java
+++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java
@@ -14522,6 +14522,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
}
@Test
+ @TestMetadata("kt52782.kt")
+ public void testKt52782() throws Exception {
+ runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/kt52782.kt");
+ }
+
+ @Test
@TestMetadata("memberScopeOfCaptured.kt")
public void testMemberScopeOfCaptured() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/memberScopeOfCaptured.kt");
diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java
index 311449478d0..b3b51063ff2 100644
--- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java
+++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java
@@ -14522,6 +14522,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
}
@Test
+ @TestMetadata("kt52782.kt")
+ public void testKt52782() throws Exception {
+ runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/kt52782.kt");
+ }
+
+ @Test
@TestMetadata("memberScopeOfCaptured.kt")
public void testMemberScopeOfCaptured() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/memberScopeOfCaptured.kt");
diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/NewTypeSubstitutor.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/NewTypeSubstitutor.kt
index 6f1b4f79e37..6f5759dc0aa 100644
--- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/NewTypeSubstitutor.kt
+++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/NewTypeSubstitutor.kt
@@ -106,8 +106,8 @@ interface NewTypeSubstitutor : TypeSubstitutorMarker {
val innerType = capturedType.lowerType ?: capturedType.constructor.projection.type.unwrap()
val substitutedInnerType = substitute(innerType, keepAnnotation, runCapturedChecks = false)
- val substitutedSuperTypes =
- capturedType.constructor.supertypes.map { substitute(it, keepAnnotation, runCapturedChecks = false) ?: it }
+ val (projectionSupertype, boundSupertypes) =
+ capturedType.constructor.transformSupertypes { substitute(it, keepAnnotation, runCapturedChecks = false) ?: it }
if (substitutedInnerType != null) {
return if (substitutedInnerType.isCaptured()) substitutedInnerType else {
@@ -116,7 +116,7 @@ interface NewTypeSubstitutor : TypeSubstitutorMarker {
NewCapturedTypeConstructor(
TypeProjectionImpl(typeConstructor.projection.projectionKind, substitutedInnerType),
typeParameter = typeConstructor.typeParameter
- ).also { it.initializeSupertypes(substitutedSuperTypes) },
+ ).also { it.initializeSupertypes(projectionSupertype, boundSupertypes) },
lowerType = if (capturedType.lowerType != null) substitutedInnerType else null
)
}
diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/kt52782.kt b/compiler/testData/diagnostics/tests/inference/capturedTypes/kt52782.kt
new file mode 100644
index 00000000000..1b8cb3ea392
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/kt52782.kt
@@ -0,0 +1,13 @@
+// FIR_IDENTICAL
+// FILE: Foo.java
+public abstract class Foo<K extends Bar<? extends Foo<K>>> {
+ abstract String getTest();
+}
+
+// FILE: Bar.java
+public abstract class Bar<T extends Foo<? extends Bar<T>>> {}
+
+// FILE: main.kt
+fun box(foo: Foo<*>) {
+ foo.test // unresolved in 1.7.0, OK before
+}
diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/kt52782.txt b/compiler/testData/diagnostics/tests/inference/capturedTypes/kt52782.txt
new file mode 100644
index 00000000000..b1d922751e5
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/kt52782.txt
@@ -0,0 +1,18 @@
+package
+
+public fun box(/*0*/ foo: Foo<*>): kotlin.Unit
+
+public abstract class Bar</*0*/ T : Foo<out Bar<T!>!>!> {
+ public constructor Bar</*0*/ T : Foo<out Bar<T!>!>!>()
+ 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 abstract class Foo</*0*/ K : Bar<out Foo<K!>!>!> {
+ public constructor Foo</*0*/ K : Bar<out Foo<K!>!>!>()
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public/*package*/ abstract fun getTest(): kotlin.String!
+ 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/tests/inference/kt47316.kt b/compiler/testData/diagnostics/tests/inference/kt47316.kt
index f881ef0e15d..b36c5dcf9df 100644
--- a/compiler/testData/diagnostics/tests/inference/kt47316.kt
+++ b/compiler/testData/diagnostics/tests/inference/kt47316.kt
@@ -30,7 +30,7 @@ fun String.asFsdAddress(): String {
fun box(): String {
val state = Test().state
if (state is GoBuildingRunningState<*>) {
- state.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>buildingWorkingDirectory<!>.<!DEBUG_INFO_MISSING_UNRESOLVED!>asFsdAddress<!>()
+ <!DEBUG_INFO_SMARTCAST!>state<!>.buildingWorkingDirectory.asFsdAddress()
}
return "OK"
}
diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java
index 614e4e99be2..73ddf114944 100644
--- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java
+++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java
@@ -14528,6 +14528,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
}
@Test
+ @TestMetadata("kt52782.kt")
+ public void testKt52782() throws Exception {
+ runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/kt52782.kt");
+ }
+
+ @Test
@TestMetadata("memberScopeOfCaptured.kt")
public void testMemberScopeOfCaptured() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/memberScopeOfCaptured.kt");
diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java
index 4dd95575857..2703a658533 100644
--- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java
+++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java
@@ -13961,11 +13961,6 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Fir extends AbstractLightAnalysisModeTest {
- @TestMetadata("flexibleIntegerLiterals.kt")
- public void ignoreFlexibleIntegerLiterals() throws Exception {
- runTest("compiler/testData/codegen/box/fir/flexibleIntegerLiterals.kt");
- }
-
@TestMetadata("SuspendExtension.kt")
public void ignoreSuspendExtension() throws Exception {
runTest("compiler/testData/codegen/box/fir/SuspendExtension.kt");
@@ -14019,6 +14014,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/fir/Fir2IrClassifierStorage.kt");
}
+ @TestMetadata("flexibleIntegerLiterals.kt")
+ public void testFlexibleIntegerLiterals() throws Exception {
+ runTest("compiler/testData/codegen/box/fir/flexibleIntegerLiterals.kt");
+ }
+
@TestMetadata("incorrectBytecodeWithEnhancedNullability.kt")
public void testIncorrectBytecodeWithEnhancedNullability() throws Exception {
runTest("compiler/testData/codegen/box/fir/incorrectBytecodeWithEnhancedNullability.kt");
diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewCapturedType.kt b/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewCapturedType.kt
index 55eb1b8207a..44093c37c4d 100644
--- a/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewCapturedType.kt
+++ b/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewCapturedType.kt
@@ -173,16 +173,16 @@ private fun captureArguments(type: UnwrappedType, status: CaptureStatus): List<T
val newProjection = capturedArguments[index]
if (oldProjection.projectionKind == Variance.INVARIANT) continue
- val capturedTypeSupertypes = type.constructor.parameters[index].upperBounds.mapTo(mutableListOf()) {
+ val boundSupertypes = type.constructor.parameters[index].upperBounds.mapTo(mutableListOf()) {
KotlinTypePreparator.Default.prepareType(substitutor.safeSubstitute(it, Variance.INVARIANT).unwrap())
}
- if (!oldProjection.isStarProjection && oldProjection.projectionKind == Variance.OUT_VARIANCE) {
- capturedTypeSupertypes += KotlinTypePreparator.Default.prepareType(oldProjection.type.unwrap())
- }
+ val projectionSupertype = if (!oldProjection.isStarProjection && oldProjection.projectionKind == Variance.OUT_VARIANCE) {
+ KotlinTypePreparator.Default.prepareType(oldProjection.type.unwrap())
+ } else null
val capturedType = newProjection.type as NewCapturedType
- capturedType.constructor.initializeSupertypes(capturedTypeSupertypes)
+ capturedType.constructor.initializeSupertypes(projectionSupertype, boundSupertypes)
}
return capturedArguments
@@ -243,18 +243,32 @@ class NewCapturedTypeConstructor(
original: NewCapturedTypeConstructor? = null
) : this(projection, { supertypes }, original)
- private val _supertypes by lazy(LazyThreadSafetyMode.PUBLICATION) {
+ // supertypes from the corresponding type parameter upper bounds
+ private val boundSupertypes by lazy(LazyThreadSafetyMode.PUBLICATION) {
supertypesComputation?.invoke()
}
- fun initializeSupertypes(supertypes: List<UnwrappedType>) {
+ private var projectionSupertype: UnwrappedType? = null
+
+ fun initializeSupertypes(projectionSupertype: UnwrappedType?, boundSupertypes: List<UnwrappedType>) {
assert(this.supertypesComputation == null) {
- "Already initialized! oldValue = ${this.supertypesComputation}, newValue = $supertypes"
+ "Already initialized! oldValue = ${this.supertypesComputation}, newValue = $boundSupertypes"
}
- this.supertypesComputation = { supertypes }
+ this.projectionSupertype = projectionSupertype
+ this.supertypesComputation = { boundSupertypes }
+ }
+
+ override fun getSupertypes(): List<UnwrappedType> = buildList {
+ projectionSupertype?.let { add(it) }
+ boundSupertypes?.let { addAll(it) }
+ }
+
+ fun transformSupertypes(transformation: (UnwrappedType) -> UnwrappedType): Pair<UnwrappedType?, List<UnwrappedType>> {
+ val projectionSupertypeTransformed = projectionSupertype?.let(transformation)
+ val boundSupertypesTransformed = boundSupertypes?.map(transformation) ?: emptyList()
+ return projectionSupertypeTransformed to boundSupertypesTransformed
}
- override fun getSupertypes() = _supertypes ?: emptyList()
override fun getParameters(): List<TypeParameterDescriptor> = emptyList()
override fun isFinal() = false