From a8275c99a315dacb1fd5a71e3893bf2a7a480b02 Mon Sep 17 00:00:00 2001 From: Nikita Bobko Date: Tue, 12 Mar 2024 17:34:47 +0100 Subject: [PATCH] [FIR, IR] Check for strict subtypes during actualization ^KT-65775 Fixed Review: https://jetbrains.team/p/kt/reviews/14906/timeline --- ...CompilerTestFE10TestdataTestGenerated.java | 6 ++++++ ...sticCompilerFE10TestDataTestGenerated.java | 6 ++++++ ...DiagnosticsWithLightTreeTestGenerated.java | 6 ++++++ ...endMPPDiagnosticsWithPsiTestGenerated.java | 6 ++++++ .../mpp/FirExpectActualMatchingContextImpl.kt | 9 +++------ .../IrExpectActualMatchingContext.kt | 6 +++--- .../calls/mpp/AbstractExpectActualChecker.kt | 7 +++---- .../calls/mpp/ExpectActualMatchingContext.kt | 6 +++--- .../multiplatform/actualTypealiasCycle.fir.kt | 20 +++++++++++++++++++ .../multiplatform/actualTypealiasCycle.kt | 20 +++++++++++++++++++ .../multiplatform/actualTypealiasCycle.ll.kt | 20 +++++++++++++++++++ .../test/runners/DiagnosticTestGenerated.java | 6 ++++++ 12 files changed, 102 insertions(+), 16 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/multiplatform/actualTypealiasCycle.fir.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/actualTypealiasCycle.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/actualTypealiasCycle.ll.kt diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java index 8bf236d45ad..484e3af46e6 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java @@ -24765,6 +24765,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia runTest("compiler/testData/diagnostics/tests/multiplatform/actualMissingConstructor.kt"); } + @Test + @TestMetadata("actualTypealiasCycle.kt") + public void testActualTypealiasCycle() { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualTypealiasCycle.kt"); + } + @Test @TestMetadata("actualTypealiasForNotExpectClass.kt") public void testActualTypealiasForNotExpectClass() { diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java index d67338c3110..023c1cc6fc5 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java @@ -24765,6 +24765,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated runTest("compiler/testData/diagnostics/tests/multiplatform/actualMissingConstructor.kt"); } + @Test + @TestMetadata("actualTypealiasCycle.kt") + public void testActualTypealiasCycle() { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualTypealiasCycle.kt"); + } + @Test @TestMetadata("actualTypealiasForNotExpectClass.kt") public void testActualTypealiasForNotExpectClass() { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated.java index 9fdd2c1d3b7..5258c8dc346 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated.java @@ -32,6 +32,12 @@ public class FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated extends Abst runTest("compiler/testData/diagnostics/tests/multiplatform/actualMissingConstructor.kt"); } + @Test + @TestMetadata("actualTypealiasCycle.kt") + public void testActualTypealiasCycle() { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualTypealiasCycle.kt"); + } + @Test @TestMetadata("actualTypealiasForNotExpectClass.kt") public void testActualTypealiasForNotExpectClass() { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithPsiTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithPsiTestGenerated.java index abd0a72212d..870f81cc6e1 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithPsiTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithPsiTestGenerated.java @@ -32,6 +32,12 @@ public class FirOldFrontendMPPDiagnosticsWithPsiTestGenerated extends AbstractFi runTest("compiler/testData/diagnostics/tests/multiplatform/actualMissingConstructor.kt"); } + @Test + @TestMetadata("actualTypealiasCycle.kt") + public void testActualTypealiasCycle() { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualTypealiasCycle.kt"); + } + @Test @TestMetadata("actualTypealiasForNotExpectClass.kt") public void testActualTypealiasForNotExpectClass() { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/mpp/FirExpectActualMatchingContextImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/mpp/FirExpectActualMatchingContextImpl.kt index d50ce8548cc..1a7840de19e 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/mpp/FirExpectActualMatchingContextImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/mpp/FirExpectActualMatchingContextImpl.kt @@ -15,8 +15,6 @@ import org.jetbrains.kotlin.fir.declarations.utils.isExpect import org.jetbrains.kotlin.fir.declarations.utils.isJava import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.resolve.* -import org.jetbrains.kotlin.fir.resolve.providers.getRegularClassSymbolByClassId -import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.resolve.providers.toSymbol import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.scopes.* @@ -35,7 +33,6 @@ import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext.Annota import org.jetbrains.kotlin.resolve.checkers.OptInNames import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualMatchingCompatibility import org.jetbrains.kotlin.types.AbstractTypeChecker -import org.jetbrains.kotlin.types.AbstractTypeRefiner import org.jetbrains.kotlin.types.TypeCheckerState import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.model.* @@ -346,11 +343,11 @@ class FirExpectActualMatchingContextImpl private constructor( return ConeClassLikeTypeImpl(lookupTag, argumentsWithOutProjection, isNullable) } - override fun actualTypeIsSubtypeOfExpectType(expectType: KotlinTypeMarker, actualType: KotlinTypeMarker): Boolean { + override fun isSubtypeOf(superType: KotlinTypeMarker, subType: KotlinTypeMarker): Boolean { return AbstractTypeChecker.isSubtypeOf( createTypeCheckerState(), - subType = actualType, - superType = expectType + subType = subType, + superType = superType ) } diff --git a/compiler/ir/ir.actualization/src/main/kotlin/org/jetbrains/kotlin/backend/common/actualizer/IrExpectActualMatchingContext.kt b/compiler/ir/ir.actualization/src/main/kotlin/org/jetbrains/kotlin/backend/common/actualizer/IrExpectActualMatchingContext.kt index a9467147aae..360405315e4 100644 --- a/compiler/ir/ir.actualization/src/main/kotlin/org/jetbrains/kotlin/backend/common/actualizer/IrExpectActualMatchingContext.kt +++ b/compiler/ir/ir.actualization/src/main/kotlin/org/jetbrains/kotlin/backend/common/actualizer/IrExpectActualMatchingContext.kt @@ -393,11 +393,11 @@ internal abstract class IrExpectActualMatchingContext( return typeContext.newTypeCheckerState(errorTypesEqualToAnything = true, stubTypesEqualToAnything = false) } - override fun actualTypeIsSubtypeOfExpectType(expectType: KotlinTypeMarker, actualType: KotlinTypeMarker): Boolean { + override fun isSubtypeOf(superType: KotlinTypeMarker, subType: KotlinTypeMarker): Boolean { return AbstractTypeChecker.isSubtypeOf( createTypeCheckerState(), - subType = actualType.actualize(), - superType = expectType.actualize() + subType = subType.actualize(), + superType = superType.actualize() ) } diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualChecker.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualChecker.kt index 081a146a0b9..5a3ae2f5c8c 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualChecker.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualChecker.kt @@ -165,10 +165,9 @@ object AbstractExpectActualChecker { val expectSupertypes = expectClassSymbol.superTypes.filterNot { it.typeConstructor().isAnyConstructor() } val actualType = actualClassSymbol.defaultType return expectSupertypes.all { expectSupertype -> - actualTypeIsSubtypeOfExpectType( - expectType = substitutor.safeSubstitute(expectSupertype), - actualType = actualType - ) + val expectType = substitutor.safeSubstitute(expectSupertype) + isSubtypeOf(superType = expectType, subType = actualType) && + !isSubtypeOf(superType = actualType, subType = expectType) } } diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/ExpectActualMatchingContext.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/ExpectActualMatchingContext.kt index cb577b9e6ae..171eecc6216 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/ExpectActualMatchingContext.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/ExpectActualMatchingContext.kt @@ -131,9 +131,9 @@ interface ExpectActualMatchingContext : TypeSystemC dynamicTypesEqualToAnything: Boolean = true ): Boolean - fun actualTypeIsSubtypeOfExpectType( - expectType: KotlinTypeMarker, - actualType: KotlinTypeMarker + fun isSubtypeOf( + superType: KotlinTypeMarker, + subType: KotlinTypeMarker ): Boolean fun RegularClassSymbolMarker.isNotSamInterface(): Boolean diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualTypealiasCycle.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualTypealiasCycle.fir.kt new file mode 100644 index 00000000000..2dbb94c83d4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualTypealiasCycle.fir.kt @@ -0,0 +1,20 @@ +// MODULE: m1-common +// FILE: common.kt + +open class A {} +expect class B : A + +expect open class A2() {} +expect open class B2 : A2 {} + +expect open class A3 + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual typealias B = A + +actual typealias A2 = B2 +actual open class B2 {} + +actual typealias A3 = Any diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualTypealiasCycle.kt b/compiler/testData/diagnostics/tests/multiplatform/actualTypealiasCycle.kt new file mode 100644 index 00000000000..abc48911cb4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualTypealiasCycle.kt @@ -0,0 +1,20 @@ +// MODULE: m1-common +// FILE: common.kt + +open class A {} +expect class B : A + +expect open class A2() {} +expect open class B2 : A2 {} + +expect open class A3 + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual typealias B = A + +actual typealias A2 = B2 +actual open class B2 {} + +actual typealias A3 = Any diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualTypealiasCycle.ll.kt b/compiler/testData/diagnostics/tests/multiplatform/actualTypealiasCycle.ll.kt new file mode 100644 index 00000000000..ad972f29f19 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualTypealiasCycle.ll.kt @@ -0,0 +1,20 @@ +// MODULE: m1-common +// FILE: common.kt + +open class A {} +expect class B : A + +expect open class A2() {} +expect open class B2 : A2 {} + +expect open class A3 + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual typealias B = A + +actual typealias A2 = B2 +actual open class B2 {} + +actual typealias A3 = Any 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 1b6cb00d1bf..464877eb2a3 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 @@ -24765,6 +24765,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/multiplatform/actualMissingConstructor.kt"); } + @Test + @TestMetadata("actualTypealiasCycle.kt") + public void testActualTypealiasCycle() { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualTypealiasCycle.kt"); + } + @Test @TestMetadata("actualTypealiasForNotExpectClass.kt") public void testActualTypealiasForNotExpectClass() {