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 8809e6347bf..5ce4977969f 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 @@ -25043,6 +25043,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/nonGenericRawMember.kt"); } + @Test + @TestMetadata("nonProjectedInnerErasure.kt") + public void testNonProjectedInnerErasure() throws Exception { + runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/nonProjectedInnerErasure.kt"); + } + @Test @TestMetadata("nonRawArraysInRawType.kt") public void testNonRawArraysInRawType() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java index 9435ea5623c..965f15bfdb5 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java @@ -25043,6 +25043,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/nonGenericRawMember.kt"); } + @Test + @TestMetadata("nonProjectedInnerErasure.kt") + public void testNonProjectedInnerErasure() throws Exception { + runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/nonProjectedInnerErasure.kt"); + } + @Test @TestMetadata("nonRawArraysInRawType.kt") public void testNonRawArraysInRawType() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java index 1f552683bdc..755d066d0a2 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java @@ -25049,6 +25049,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/nonGenericRawMember.kt"); } + @Test + @TestMetadata("nonProjectedInnerErasure.kt") + public void testNonProjectedInnerErasure() throws Exception { + runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/nonProjectedInnerErasure.kt"); + } + @Test @TestMetadata("nonRawArraysInRawType.kt") public void testNonRawArraysInRawType() throws Exception { diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt index 6fe3c77723d..3d6234f5c24 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt @@ -395,7 +395,7 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo override fun KotlinTypeMarker.eraseContainingTypeParameters(): KotlinTypeMarker { val typeParameterErasureMap = this.extractTypeParameters() .map { (it as ConeTypeParameterLookupTag).typeParameterSymbol } - .eraseToUpperBoundsAssociated(session, intersectUpperBounds = true, eraseRecursively = true) + .eraseToUpperBoundsAssociated(session) val substitutor by lazy { ConeSubstitutorByMap(typeParameterErasureMap, session) } val typeWithErasedTypeParameters = if (argumentsCount() != 0) { replaceArgumentsDeeply { diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt index ca7482d0fe9..4710d95d69a 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt @@ -18,7 +18,6 @@ import org.jetbrains.kotlin.fir.declarations.utils.isExpect import org.jetbrains.kotlin.fir.declarations.utils.modality import org.jetbrains.kotlin.fir.declarations.utils.visibility import org.jetbrains.kotlin.fir.diagnostics.ConeRecursiveTypeParameterDuringErasureError -import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap import org.jetbrains.kotlin.fir.resolve.toSymbol @@ -627,12 +626,10 @@ fun KotlinTypeMarker.isSubtypeOf(context: TypeCheckerProviderContext, type: Kotl fun List.eraseToUpperBoundsAssociated( session: FirSession, - intersectUpperBounds: Boolean = false, - eraseRecursively: Boolean = false ): Map { val cache = mutableMapOf() return associateWith { - it.fir.eraseToUpperBound(session, cache, intersectUpperBounds, eraseRecursively, boundsShouldBeResolved = true) + it.fir.eraseToUpperBound(session, cache, mode = EraseUpperBoundMode.FOR_EMPTY_INTERSECTION_CHECK) } } @@ -640,37 +637,32 @@ fun List.getProjectionsForRawType(session: FirSession): val cache = mutableMapOf() return Array(size) { index -> this[index].fir.eraseToUpperBound( - session, cache, intersectUpperBounds = false, eraseRecursively = false, boundsShouldBeResolved = false + session, cache, mode = EraseUpperBoundMode.FOR_RAW_TYPE_ERASURE ) } } +private enum class EraseUpperBoundMode { + FOR_RAW_TYPE_ERASURE, + FOR_EMPTY_INTERSECTION_CHECK +} + private fun FirTypeParameter.eraseToUpperBound( session: FirSession, cache: MutableMap, - intersectUpperBounds: Boolean, - eraseRecursively: Boolean, - boundsShouldBeResolved: Boolean + mode: EraseUpperBoundMode, ): ConeKotlinType { fun eraseAsUpperBound(type: FirResolvedTypeRef) = - type.coneType.eraseAsUpperBound(session, cache, intersectUpperBounds, eraseRecursively, boundsShouldBeResolved) + type.coneType.eraseAsUpperBound(session, cache, mode) return cache.getOrPut(this) { // Mark to avoid loops. cache[this] = ConeErrorType(ConeRecursiveTypeParameterDuringErasureError(name)) - // We can assume that Java type parameter bounds are already converted. - if (intersectUpperBounds) { + if (mode == EraseUpperBoundMode.FOR_EMPTY_INTERSECTION_CHECK) { ConeTypeIntersector.intersectTypes(session.typeContext, symbol.resolvedBounds.map(::eraseAsUpperBound)) } else { - val boundTypeRef = bounds.first() - when { - boundTypeRef is FirResolvedTypeRef -> eraseAsUpperBound(boundTypeRef) - // As we currently know, a raw supertype is the only example - // when bounds can be unresolved here (see the branch below). - // This exception is expected to find other possible occurrences, if any. - boundsShouldBeResolved -> throw IllegalStateException( - "Bounds of ${render()} type parameter of ${containingDeclarationSymbol.fir.render()} aren't resolved" - ) + when (val boundTypeRef = bounds.first()) { + is FirResolvedTypeRef -> eraseAsUpperBound(boundTypeRef) // While resolving raw supertype in Java we may encounter a situation // when this supertype constructor has some type parameters and // their bounds aren't yet resolved. See KT-56630 and comments inside. @@ -685,8 +677,7 @@ private fun FirTypeParameter.eraseToUpperBound( private fun SimpleTypeMarker.eraseArgumentsDeeply( typeContext: ConeInferenceContext, cache: MutableMap, - intersectUpperBounds: Boolean, - boundsShouldBeResolved: Boolean + mode: EraseUpperBoundMode, ): ConeKotlinType = with(typeContext) { replaceArgumentsDeeply { typeArgument -> if (typeArgument.isStarProjection()) @@ -698,30 +689,28 @@ private fun SimpleTypeMarker.eraseArgumentsDeeply( typeConstructor as ConeTypeParameterLookupTag val erasedType = typeConstructor.typeParameterSymbol.fir.eraseToUpperBound( - session, cache, intersectUpperBounds, eraseRecursively = true, boundsShouldBeResolved = boundsShouldBeResolved + session, cache, mode = mode ) if ((erasedType as? ConeErrorType)?.diagnostic is ConeRecursiveTypeParameterDuringErasureError) return@replaceArgumentsDeeply ConeStarProjection - erasedType.toTypeProjection(ProjectionKind.OUT) + // See the similar semantics at RawProjectionComputer::computeProjection + if (mode == EraseUpperBoundMode.FOR_RAW_TYPE_ERASURE) + erasedType + else + erasedType.toTypeProjection(ProjectionKind.OUT) } as ConeKotlinType } private fun ConeKotlinType.eraseAsUpperBound( session: FirSession, cache: MutableMap, - intersectUpperBounds: Boolean, - eraseRecursively: Boolean, - boundsShouldBeResolved: Boolean + mode: EraseUpperBoundMode, ): ConeKotlinType = when (this) { is ConeClassLikeType -> { - if (eraseRecursively) { - eraseArgumentsDeeply(session.typeContext, cache, intersectUpperBounds, boundsShouldBeResolved) - } else { - withArguments(typeArguments.map { ConeStarProjection }.toTypedArray()) - } + eraseArgumentsDeeply(session.typeContext, cache, mode) } is ConeFlexibleType -> @@ -729,19 +718,19 @@ private fun ConeKotlinType.eraseAsUpperBound( // so there is no exponential complexity here due to cache lookups. coneFlexibleOrSimpleType( session.typeContext, - lowerBound.eraseAsUpperBound(session, cache, intersectUpperBounds, eraseRecursively, boundsShouldBeResolved), - upperBound.eraseAsUpperBound(session, cache, intersectUpperBounds, eraseRecursively, boundsShouldBeResolved) + lowerBound.eraseAsUpperBound(session, cache, mode), + upperBound.eraseAsUpperBound(session, cache, mode) ) is ConeTypeParameterType -> lookupTag.typeParameterSymbol.fir.eraseToUpperBound( - session, cache, intersectUpperBounds, eraseRecursively, boundsShouldBeResolved + session, cache, mode ).let { if (isNullable) it.withNullability(nullability, session.typeContext) else it } is ConeDefinitelyNotNullType -> - original.eraseAsUpperBound(session, cache, intersectUpperBounds, eraseRecursively, boundsShouldBeResolved) + original.eraseAsUpperBound(session, cache, mode) .makeConeTypeDefinitelyNotNullOrNotNull(session.typeContext) else -> error("unexpected Java type parameter upper bound kind: $this") diff --git a/compiler/testData/diagnostics/tests/platformTypes/rawTypes/interdependentTypeParameters.fir.kt b/compiler/testData/diagnostics/tests/platformTypes/rawTypes/interdependentTypeParameters.fir.kt index 3ecebfdf979..73e8d90ef06 100644 --- a/compiler/testData/diagnostics/tests/platformTypes/rawTypes/interdependentTypeParameters.fir.kt +++ b/compiler/testData/diagnostics/tests/platformTypes/rawTypes/interdependentTypeParameters.fir.kt @@ -8,5 +8,5 @@ public class Foo, P2 extends Boo, P3 exte // FILE: main.kt fun main() { - val x = ..Boo<*>?!, Boo<*>..Boo<*>?!, Boo<*>..Boo<*>?!, Boo<*>..Boo<*>?!>..Foo<*, *, *, *>?!")!>Foo.test1() + val x = ..Boo<*>?!>..Boo..Boo<*>?!>?!, Boo<*>..Boo<*>?!, Boo..Boo<*>?!>..Boo..Boo<*>?!>?!>..Boo..Boo<*>?!>..Boo..Boo<*>?!>?!>?!, Boo..Boo<*>?!>..Boo..Boo<*>?!>?!>..Boo..Boo<*>?!>..Boo..Boo<*>?!>?!>?!>..Foo<*, *, *, *>?!")!>Foo.test1() } diff --git a/compiler/testData/diagnostics/tests/platformTypes/rawTypes/interdependentTypeParametersFromKotlin.fir.kt b/compiler/testData/diagnostics/tests/platformTypes/rawTypes/interdependentTypeParametersFromKotlin.fir.kt index 201392b029a..e35849f58bf 100644 --- a/compiler/testData/diagnostics/tests/platformTypes/rawTypes/interdependentTypeParametersFromKotlin.fir.kt +++ b/compiler/testData/diagnostics/tests/platformTypes/rawTypes/interdependentTypeParametersFromKotlin.fir.kt @@ -8,5 +8,5 @@ class Foo, P2 : Boo, P3 : Boo, P4 : // FILE: main.kt fun main() { - val x = , Boo<*, *, *>, Boo<*, *, *>, Boo<*, *, *>>..Foo<*, *, *, *>?!")!>Boo.test1() + val x = >, Boo<*, *, *>>, Boo<*, *, Boo<*, *, *>>, Boo<*, *, *>>, Boo<*, Boo<*, *, Boo<*, *, *>>, Boo<*, *, *>>, Boo<*, *, Boo<*, *, *>>, Boo<*, *, *>>..Foo<*, *, *, *>?!")!>Boo.test1() } diff --git a/compiler/testData/diagnostics/tests/platformTypes/rawTypes/intermediateRecursion.fir.kt b/compiler/testData/diagnostics/tests/platformTypes/rawTypes/intermediateRecursion.fir.kt index dd05a659545..c3e511f8209 100644 --- a/compiler/testData/diagnostics/tests/platformTypes/rawTypes/intermediateRecursion.fir.kt +++ b/compiler/testData/diagnostics/tests/platformTypes/rawTypes/intermediateRecursion.fir.kt @@ -9,5 +9,5 @@ public class Foo, K extends Boo, X extends Boo> { // FILE: main.kt fun main() { - val x = ..Boo<*>?!, Boo<*>..Boo<*>?!, Boo<*>..Boo<*>?!>..Foo<*, *, *>?!")!>Foo.test1().test2() + val x = ..Boo<*>?!>..Boo..Boo<*>?!>?!>..Boo..Boo<*>?!>..Boo..Boo<*>?!>?!>?!, Boo..Boo<*>?!>..Boo..Boo<*>?!>?!, Boo<*>..Boo<*>?!>..Foo<*, *, *>?!")!>Foo.test1().test2() } diff --git a/compiler/testData/diagnostics/tests/platformTypes/rawTypes/nonProjectedInnerErasure.kt b/compiler/testData/diagnostics/tests/platformTypes/rawTypes/nonProjectedInnerErasure.kt new file mode 100644 index 00000000000..87bba19b3ac --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/rawTypes/nonProjectedInnerErasure.kt @@ -0,0 +1,17 @@ +// FIR_IDENTICAL +// ISSUE: KT-57198 +// FILE: CustomGdbServerRunConfiguration.java + +public class CustomGdbServerRunConfiguration implements CidrRunConfiguration {} + +// FILE: main.kt +interface CidrBuildTarget +interface CidrRunConfiguration> + +fun applyEditorTo(arg: CidrRunConfiguration>) {} + +fun main() { + // Previously, for CidrRunConfiguration raw type, it's lower bound was resolved as CidrRunConfiguration> in K2 + // That is not a subtype of CidrRunConfiguration> + applyEditorTo(CustomGdbServerRunConfiguration()) // K1: ok, K2: was ARGUMENT_TYPE_MISMATCH +} diff --git a/compiler/testData/loadJava/compiledJava/signaturePropagation/RawSuperTypeWithRecursiveBoundMultipleParameters.fir.txt b/compiler/testData/loadJava/compiledJava/signaturePropagation/RawSuperTypeWithRecursiveBoundMultipleParameters.fir.txt index a41a9910dab..7f40b5ae2a6 100644 --- a/compiler/testData/loadJava/compiledJava/signaturePropagation/RawSuperTypeWithRecursiveBoundMultipleParameters.fir.txt +++ b/compiler/testData/loadJava/compiledJava/signaturePropagation/RawSuperTypeWithRecursiveBoundMultipleParameters.fir.txt @@ -1,10 +1,10 @@ public open class RawSuperTypeWithRecursiveBoundMultipleParameters : R|kotlin/Any| { public constructor(): R|test/RawSuperTypeWithRecursiveBoundMultipleParameters| - public open inner class Derived : R|kotlin/Any|, R|Raw type test/RawSuperTypeWithRecursiveBoundMultipleParameters.Super, test/RawSuperTypeWithRecursiveBoundMultipleParameters.Super<*, *>?>>| { + public open inner class Derived : R|kotlin/Any|, R|Raw type test/RawSuperTypeWithRecursiveBoundMultipleParameters.Super, test/RawSuperTypeWithRecursiveBoundMultipleParameters.Super?>>| { public open fun foo(o: R|kotlin/Any!|, o1: R|kotlin/Any!|): R|kotlin/Unit| - @R|java/lang/Override|() public open fun foo(r: R|kotlin/Any!|, t: R|ft, test/RawSuperTypeWithRecursiveBoundMultipleParameters.Super<*, *>?>>, test/RawSuperTypeWithRecursiveBoundMultipleParameters.Super<*, *>?>|): R|kotlin/Unit| + @R|java/lang/Override|() public open fun foo(r: R|kotlin/Any!|, t: R|ft, test/RawSuperTypeWithRecursiveBoundMultipleParameters.Super?>>, test/RawSuperTypeWithRecursiveBoundMultipleParameters.Super<*, *>?>|): R|kotlin/Unit| @R|java/lang/Override|() public open fun dummy(): R|kotlin/Unit| 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 caa4b14f780..298b46814e1 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 @@ -25049,6 +25049,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/nonGenericRawMember.kt"); } + @Test + @TestMetadata("nonProjectedInnerErasure.kt") + public void testNonProjectedInnerErasure() throws Exception { + runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/nonProjectedInnerErasure.kt"); + } + @Test @TestMetadata("nonRawArraysInRawType.kt") public void testNonRawArraysInRawType() throws Exception {