diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt index 05a19202422..ae2b0feda3e 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -3848,6 +3848,46 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.INCOMPATIBLE_ENUM_COMPARISON) { firDiagnostic -> + IncompatibleEnumComparisonImpl( + firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a), + firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.b), + firDiagnostic as KtPsiDiagnostic, + token, + ) + } + add(FirErrors.FORBIDDEN_IDENTITY_EQUALS) { firDiagnostic -> + ForbiddenIdentityEqualsImpl( + firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a), + firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.b), + firDiagnostic as KtPsiDiagnostic, + token, + ) + } + add(FirErrors.FORBIDDEN_IDENTITY_EQUALS_WARNING) { firDiagnostic -> + ForbiddenIdentityEqualsWarningImpl( + firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a), + firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.b), + firDiagnostic as KtPsiDiagnostic, + token, + ) + } + add(FirErrors.DEPRECATED_IDENTITY_EQUALS) { firDiagnostic -> + DeprecatedIdentityEqualsImpl( + firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a), + firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.b), + firDiagnostic as KtPsiDiagnostic, + token, + ) + } + add(FirErrors.IMPLICIT_BOXING_IN_IDENTITY_EQUALS) { firDiagnostic -> + ImplicitBoxingInIdentityEqualsImpl( + firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a), + firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.b), + firDiagnostic as KtPsiDiagnostic, + token, + ) + } add(FirErrors.INC_DEC_SHOULD_NOT_RETURN_UNIT) { firDiagnostic -> IncDecShouldNotReturnUnitImpl( firDiagnostic as KtPsiDiagnostic, diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt index e95083f3e77..4e386836148 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt @@ -2684,6 +2684,36 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { abstract val rightType: KtType } + abstract class IncompatibleEnumComparison : KtFirDiagnostic() { + override val diagnosticClass get() = IncompatibleEnumComparison::class + abstract val leftType: KtType + abstract val rightType: KtType + } + + abstract class ForbiddenIdentityEquals : KtFirDiagnostic() { + override val diagnosticClass get() = ForbiddenIdentityEquals::class + abstract val leftType: KtType + abstract val rightType: KtType + } + + abstract class ForbiddenIdentityEqualsWarning : KtFirDiagnostic() { + override val diagnosticClass get() = ForbiddenIdentityEqualsWarning::class + abstract val leftType: KtType + abstract val rightType: KtType + } + + abstract class DeprecatedIdentityEquals : KtFirDiagnostic() { + override val diagnosticClass get() = DeprecatedIdentityEquals::class + abstract val leftType: KtType + abstract val rightType: KtType + } + + abstract class ImplicitBoxingInIdentityEquals : KtFirDiagnostic() { + override val diagnosticClass get() = ImplicitBoxingInIdentityEquals::class + abstract val leftType: KtType + abstract val rightType: KtType + } + abstract class IncDecShouldNotReturnUnit : KtFirDiagnostic() { override val diagnosticClass get() = IncDecShouldNotReturnUnit::class } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index 9ce30cf19c9..6b50261787f 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -3235,6 +3235,41 @@ internal class IncompatibleEnumComparisonErrorImpl( override val token: KtLifetimeToken, ) : KtFirDiagnostic.IncompatibleEnumComparisonError(), KtAbstractFirDiagnostic +internal class IncompatibleEnumComparisonImpl( + override val leftType: KtType, + override val rightType: KtType, + override val firDiagnostic: KtPsiDiagnostic, + override val token: KtLifetimeToken, +) : KtFirDiagnostic.IncompatibleEnumComparison(), KtAbstractFirDiagnostic + +internal class ForbiddenIdentityEqualsImpl( + override val leftType: KtType, + override val rightType: KtType, + override val firDiagnostic: KtPsiDiagnostic, + override val token: KtLifetimeToken, +) : KtFirDiagnostic.ForbiddenIdentityEquals(), KtAbstractFirDiagnostic + +internal class ForbiddenIdentityEqualsWarningImpl( + override val leftType: KtType, + override val rightType: KtType, + override val firDiagnostic: KtPsiDiagnostic, + override val token: KtLifetimeToken, +) : KtFirDiagnostic.ForbiddenIdentityEqualsWarning(), KtAbstractFirDiagnostic + +internal class DeprecatedIdentityEqualsImpl( + override val leftType: KtType, + override val rightType: KtType, + override val firDiagnostic: KtPsiDiagnostic, + override val token: KtLifetimeToken, +) : KtFirDiagnostic.DeprecatedIdentityEquals(), KtAbstractFirDiagnostic + +internal class ImplicitBoxingInIdentityEqualsImpl( + override val leftType: KtType, + override val rightType: KtType, + override val firDiagnostic: KtPsiDiagnostic, + override val token: KtLifetimeToken, +) : KtFirDiagnostic.ImplicitBoxingInIdentityEquals(), KtAbstractFirDiagnostic + internal class IncDecShouldNotReturnUnitImpl( override val firDiagnostic: KtPsiDiagnostic, override val token: KtLifetimeToken, 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 73c808c8f07..9b03ad906ae 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 @@ -159,6 +159,24 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia runTest("compiler/testData/diagnostics/tests/CompareToWithErrorType.kt"); } + @Test + @TestMetadata("comparingArbitraryClasses.kt") + public void testComparingArbitraryClasses() throws Exception { + runTest("compiler/testData/diagnostics/tests/comparingArbitraryClasses.kt"); + } + + @Test + @TestMetadata("comparingCallableReferencesWithInstanceOfJavaClass.kt") + public void testComparingCallableReferencesWithInstanceOfJavaClass() throws Exception { + runTest("compiler/testData/diagnostics/tests/comparingCallableReferencesWithInstanceOfJavaClass.kt"); + } + + @Test + @TestMetadata("comparisonOfGenericInterfaceWithGenericClass.kt") + public void testComparisonOfGenericInterfaceWithGenericClass() throws Exception { + runTest("compiler/testData/diagnostics/tests/comparisonOfGenericInterfaceWithGenericClass.kt"); + } + @Test @TestMetadata("Constants.kt") public void testConstants() throws Exception { @@ -243,6 +261,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia runTest("compiler/testData/diagnostics/tests/DiamondProperty.kt"); } + @Test + @TestMetadata("differentNumericTypesFromSmartCast.kt") + public void testDifferentNumericTypesFromSmartCast() throws Exception { + runTest("compiler/testData/diagnostics/tests/differentNumericTypesFromSmartCast.kt"); + } + @Test @TestMetadata("Dollar.kt") public void testDollar() throws Exception { @@ -255,6 +279,18 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia runTest("compiler/testData/diagnostics/tests/EnumEntryAsType.kt"); } + @Test + @TestMetadata("equalityComparisonToSelf.kt") + public void testEqualityComparisonToSelf() throws Exception { + runTest("compiler/testData/diagnostics/tests/equalityComparisonToSelf.kt"); + } + + @Test + @TestMetadata("equalityWithSmartCastInIfBlock.kt") + public void testEqualityWithSmartCastInIfBlock() throws Exception { + runTest("compiler/testData/diagnostics/tests/equalityWithSmartCastInIfBlock.kt"); + } + @Test @TestMetadata("ExtensionCallInvoke.kt") public void testExtensionCallInvoke() throws Exception { @@ -10392,6 +10428,18 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia runTest("compiler/testData/diagnostics/tests/enum/enumWithEmptyName.kt"); } + @Test + @TestMetadata("equalityOfEnumAndParameter.kt") + public void testEqualityOfEnumAndParameter() throws Exception { + runTest("compiler/testData/diagnostics/tests/enum/equalityOfEnumAndParameter.kt"); + } + + @Test + @TestMetadata("equalityOfFlexibleTypeParameters.kt") + public void testEqualityOfFlexibleTypeParameters() throws Exception { + runTest("compiler/testData/diagnostics/tests/enum/equalityOfFlexibleTypeParameters.kt"); + } + @Test @TestMetadata("ExplicitConstructorCall.kt") public void testExplicitConstructorCall() throws Exception { @@ -35359,6 +35407,30 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia runTest("compiler/testData/diagnostics/testsWithStdLib/commonCollections.kt"); } + @Test + @TestMetadata("comparingDifferentSubclassesCommonInterface.kt") + public void testComparingDifferentSubclassesCommonInterface() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/comparingDifferentSubclassesCommonInterface.kt"); + } + + @Test + @TestMetadata("comparingPlatformTypes.kt") + public void testComparingPlatformTypes() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/comparingPlatformTypes.kt"); + } + + @Test + @TestMetadata("comparingSmartCastValueToBoolean.kt") + public void testComparingSmartCastValueToBoolean() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/comparingSmartCastValueToBoolean.kt"); + } + + @Test + @TestMetadata("comparingTripleWithPair.kt") + public void testComparingTripleWithPair() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/comparingTripleWithPair.kt"); + } + @Test @TestMetadata("compileTimeUnsignedArray.kt") public void testCompileTimeUnsignedArray() throws Exception { @@ -35383,6 +35455,24 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia runTest("compiler/testData/diagnostics/testsWithStdLib/enumEntryInitialization.kt"); } + @Test + @TestMetadata("equalityCompatibilityCommonCases.kt") + public void testEqualityCompatibilityCommonCases() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityCommonCases.kt"); + } + + @Test + @TestMetadata("equalityCompatibilityOldBehavior_Off.kt") + public void testEqualityCompatibilityOldBehavior_Off() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_Off.kt"); + } + + @Test + @TestMetadata("equalityCompatibilityOldBehavior_On.kt") + public void testEqualityCompatibilityOldBehavior_On() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_On.kt"); + } + @Test @TestMetadata("exitProcess.kt") public void testExitProcess() throws Exception { 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 c596fec436c..e58d2bf3f16 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 @@ -159,6 +159,24 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated runTest("compiler/testData/diagnostics/tests/CompareToWithErrorType.kt"); } + @Test + @TestMetadata("comparingArbitraryClasses.kt") + public void testComparingArbitraryClasses() throws Exception { + runTest("compiler/testData/diagnostics/tests/comparingArbitraryClasses.kt"); + } + + @Test + @TestMetadata("comparingCallableReferencesWithInstanceOfJavaClass.kt") + public void testComparingCallableReferencesWithInstanceOfJavaClass() throws Exception { + runTest("compiler/testData/diagnostics/tests/comparingCallableReferencesWithInstanceOfJavaClass.kt"); + } + + @Test + @TestMetadata("comparisonOfGenericInterfaceWithGenericClass.kt") + public void testComparisonOfGenericInterfaceWithGenericClass() throws Exception { + runTest("compiler/testData/diagnostics/tests/comparisonOfGenericInterfaceWithGenericClass.kt"); + } + @Test @TestMetadata("Constants.kt") public void testConstants() throws Exception { @@ -243,6 +261,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated runTest("compiler/testData/diagnostics/tests/DiamondProperty.kt"); } + @Test + @TestMetadata("differentNumericTypesFromSmartCast.kt") + public void testDifferentNumericTypesFromSmartCast() throws Exception { + runTest("compiler/testData/diagnostics/tests/differentNumericTypesFromSmartCast.kt"); + } + @Test @TestMetadata("Dollar.kt") public void testDollar() throws Exception { @@ -255,6 +279,18 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated runTest("compiler/testData/diagnostics/tests/EnumEntryAsType.kt"); } + @Test + @TestMetadata("equalityComparisonToSelf.kt") + public void testEqualityComparisonToSelf() throws Exception { + runTest("compiler/testData/diagnostics/tests/equalityComparisonToSelf.kt"); + } + + @Test + @TestMetadata("equalityWithSmartCastInIfBlock.kt") + public void testEqualityWithSmartCastInIfBlock() throws Exception { + runTest("compiler/testData/diagnostics/tests/equalityWithSmartCastInIfBlock.kt"); + } + @Test @TestMetadata("ExtensionCallInvoke.kt") public void testExtensionCallInvoke() throws Exception { @@ -10392,6 +10428,18 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated runTest("compiler/testData/diagnostics/tests/enum/enumWithEmptyName.kt"); } + @Test + @TestMetadata("equalityOfEnumAndParameter.kt") + public void testEqualityOfEnumAndParameter() throws Exception { + runTest("compiler/testData/diagnostics/tests/enum/equalityOfEnumAndParameter.kt"); + } + + @Test + @TestMetadata("equalityOfFlexibleTypeParameters.kt") + public void testEqualityOfFlexibleTypeParameters() throws Exception { + runTest("compiler/testData/diagnostics/tests/enum/equalityOfFlexibleTypeParameters.kt"); + } + @Test @TestMetadata("ExplicitConstructorCall.kt") public void testExplicitConstructorCall() throws Exception { @@ -35359,6 +35407,30 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated runTest("compiler/testData/diagnostics/testsWithStdLib/commonCollections.kt"); } + @Test + @TestMetadata("comparingDifferentSubclassesCommonInterface.kt") + public void testComparingDifferentSubclassesCommonInterface() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/comparingDifferentSubclassesCommonInterface.kt"); + } + + @Test + @TestMetadata("comparingPlatformTypes.kt") + public void testComparingPlatformTypes() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/comparingPlatformTypes.kt"); + } + + @Test + @TestMetadata("comparingSmartCastValueToBoolean.kt") + public void testComparingSmartCastValueToBoolean() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/comparingSmartCastValueToBoolean.kt"); + } + + @Test + @TestMetadata("comparingTripleWithPair.kt") + public void testComparingTripleWithPair() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/comparingTripleWithPair.kt"); + } + @Test @TestMetadata("compileTimeUnsignedArray.kt") public void testCompileTimeUnsignedArray() throws Exception { @@ -35383,6 +35455,24 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated runTest("compiler/testData/diagnostics/testsWithStdLib/enumEntryInitialization.kt"); } + @Test + @TestMetadata("equalityCompatibilityCommonCases.kt") + public void testEqualityCompatibilityCommonCases() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityCommonCases.kt"); + } + + @Test + @TestMetadata("equalityCompatibilityOldBehavior_Off.kt") + public void testEqualityCompatibilityOldBehavior_Off() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_Off.kt"); + } + + @Test + @TestMetadata("equalityCompatibilityOldBehavior_On.kt") + public void testEqualityCompatibilityOldBehavior_On() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_On.kt"); + } + @Test @TestMetadata("exitProcess.kt") public void testExitProcess() throws Exception { diff --git a/compiler/fir/analysis-tests/testData/resolve/lambdaPropertyTypeInference.kt b/compiler/fir/analysis-tests/testData/resolve/lambdaPropertyTypeInference.kt index ce117889151..0d3825e0b89 100644 --- a/compiler/fir/analysis-tests/testData/resolve/lambdaPropertyTypeInference.kt +++ b/compiler/fir/analysis-tests/testData/resolve/lambdaPropertyTypeInference.kt @@ -33,7 +33,7 @@ fun case1(javaClass: JavaClass?) { } class Case1(val javaClass: JavaClass?) { - val x = if (javaClass != null) { it -> it == javaClass } else BooCase2.FILTER + val x = if (javaClass != null) { it -> it == javaClass } else BooCase2.FILTER } class BooCase1() { diff --git a/compiler/fir/analysis-tests/testData/resolve/smartcasts/nullability.kt b/compiler/fir/analysis-tests/testData/resolve/smartcasts/nullability.kt index 872fc7d95d3..9736e45d421 100644 --- a/compiler/fir/analysis-tests/testData/resolve/smartcasts/nullability.kt +++ b/compiler/fir/analysis-tests/testData/resolve/smartcasts/nullability.kt @@ -101,7 +101,7 @@ fun test_9(a: Int, b: Int?) { } b.inc() - if (a === b) { + if (a === b) { b.inc() } b.inc() @@ -111,7 +111,7 @@ fun test_9(a: Int, b: Int?) { } b.inc() - if (b === a) { + if (b === a) { b.inc() } b.inc() diff --git a/compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/priority.kt b/compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/priority.kt index 7ac70884479..937c242694a 100644 --- a/compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/priority.kt +++ b/compiler/fir/analysis-tests/testData/resolve/unqualifiedEnum/priority.kt @@ -22,12 +22,12 @@ enum class Second { val ONE = Second.THREE fun foo(f: First) = when (f) { - ONE -> 1 + ONE -> 1 TWO -> 2 } fun bar(s: Second) = when (s) { - THREE -> 3 + THREE -> 3 FOUR -> 4 } diff --git a/compiler/fir/analysis-tests/testData/resolve/whenElse.kt b/compiler/fir/analysis-tests/testData/resolve/whenElse.kt index 1e1b5cacf5d..f37c6c7bf3b 100644 --- a/compiler/fir/analysis-tests/testData/resolve/whenElse.kt +++ b/compiler/fir/analysis-tests/testData/resolve/whenElse.kt @@ -1,4 +1,3 @@ - /* * UNEXPECTED BEHAVIOUR * ISSUES: KT-37081 diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/IntersectionWithJavaString.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/IntersectionWithJavaString.kt index 97c328dfdea..3fd79de9e88 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/IntersectionWithJavaString.kt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/IntersectionWithJavaString.kt @@ -1,8 +1,9 @@ // FULL_JDK // ISSUE: KT-48113 +// STATUS: On a K2 technical meeting on Mar-27-2023 it was decided to report a warning // WITH_EXTENDED_CHECKERS fun collapse(path: String) { val result = (path as java.lang.String).replace("123", "456") - if (result !== path) {} + if (result !== path) {} } 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 b9f91e45359..bbcadcc120f 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 @@ -159,6 +159,24 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir runTest("compiler/testData/diagnostics/tests/CompareToWithErrorType.kt"); } + @Test + @TestMetadata("comparingArbitraryClasses.kt") + public void testComparingArbitraryClasses() throws Exception { + runTest("compiler/testData/diagnostics/tests/comparingArbitraryClasses.kt"); + } + + @Test + @TestMetadata("comparingCallableReferencesWithInstanceOfJavaClass.kt") + public void testComparingCallableReferencesWithInstanceOfJavaClass() throws Exception { + runTest("compiler/testData/diagnostics/tests/comparingCallableReferencesWithInstanceOfJavaClass.kt"); + } + + @Test + @TestMetadata("comparisonOfGenericInterfaceWithGenericClass.kt") + public void testComparisonOfGenericInterfaceWithGenericClass() throws Exception { + runTest("compiler/testData/diagnostics/tests/comparisonOfGenericInterfaceWithGenericClass.kt"); + } + @Test @TestMetadata("Constants.kt") public void testConstants() throws Exception { @@ -243,6 +261,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir runTest("compiler/testData/diagnostics/tests/DiamondProperty.kt"); } + @Test + @TestMetadata("differentNumericTypesFromSmartCast.kt") + public void testDifferentNumericTypesFromSmartCast() throws Exception { + runTest("compiler/testData/diagnostics/tests/differentNumericTypesFromSmartCast.kt"); + } + @Test @TestMetadata("Dollar.kt") public void testDollar() throws Exception { @@ -255,6 +279,18 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir runTest("compiler/testData/diagnostics/tests/EnumEntryAsType.kt"); } + @Test + @TestMetadata("equalityComparisonToSelf.kt") + public void testEqualityComparisonToSelf() throws Exception { + runTest("compiler/testData/diagnostics/tests/equalityComparisonToSelf.kt"); + } + + @Test + @TestMetadata("equalityWithSmartCastInIfBlock.kt") + public void testEqualityWithSmartCastInIfBlock() throws Exception { + runTest("compiler/testData/diagnostics/tests/equalityWithSmartCastInIfBlock.kt"); + } + @Test @TestMetadata("ExtensionCallInvoke.kt") public void testExtensionCallInvoke() throws Exception { @@ -10392,6 +10428,18 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir runTest("compiler/testData/diagnostics/tests/enum/enumWithEmptyName.kt"); } + @Test + @TestMetadata("equalityOfEnumAndParameter.kt") + public void testEqualityOfEnumAndParameter() throws Exception { + runTest("compiler/testData/diagnostics/tests/enum/equalityOfEnumAndParameter.kt"); + } + + @Test + @TestMetadata("equalityOfFlexibleTypeParameters.kt") + public void testEqualityOfFlexibleTypeParameters() throws Exception { + runTest("compiler/testData/diagnostics/tests/enum/equalityOfFlexibleTypeParameters.kt"); + } + @Test @TestMetadata("ExplicitConstructorCall.kt") public void testExplicitConstructorCall() throws Exception { @@ -35359,6 +35407,30 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir runTest("compiler/testData/diagnostics/testsWithStdLib/commonCollections.kt"); } + @Test + @TestMetadata("comparingDifferentSubclassesCommonInterface.kt") + public void testComparingDifferentSubclassesCommonInterface() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/comparingDifferentSubclassesCommonInterface.kt"); + } + + @Test + @TestMetadata("comparingPlatformTypes.kt") + public void testComparingPlatformTypes() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/comparingPlatformTypes.kt"); + } + + @Test + @TestMetadata("comparingSmartCastValueToBoolean.kt") + public void testComparingSmartCastValueToBoolean() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/comparingSmartCastValueToBoolean.kt"); + } + + @Test + @TestMetadata("comparingTripleWithPair.kt") + public void testComparingTripleWithPair() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/comparingTripleWithPair.kt"); + } + @Test @TestMetadata("compileTimeUnsignedArray.kt") public void testCompileTimeUnsignedArray() throws Exception { @@ -35383,6 +35455,24 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir runTest("compiler/testData/diagnostics/testsWithStdLib/enumEntryInitialization.kt"); } + @Test + @TestMetadata("equalityCompatibilityCommonCases.kt") + public void testEqualityCompatibilityCommonCases() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityCommonCases.kt"); + } + + @Test + @TestMetadata("equalityCompatibilityOldBehavior_Off.kt") + public void testEqualityCompatibilityOldBehavior_Off() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_Off.kt"); + } + + @Test + @TestMetadata("equalityCompatibilityOldBehavior_On.kt") + public void testEqualityCompatibilityOldBehavior_On() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_On.kt"); + } + @Test @TestMetadata("exitProcess.kt") public void testExitProcess() 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 f424c55b3d0..2c1c39bc7e5 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 @@ -159,6 +159,24 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia runTest("compiler/testData/diagnostics/tests/CompareToWithErrorType.kt"); } + @Test + @TestMetadata("comparingArbitraryClasses.kt") + public void testComparingArbitraryClasses() throws Exception { + runTest("compiler/testData/diagnostics/tests/comparingArbitraryClasses.kt"); + } + + @Test + @TestMetadata("comparingCallableReferencesWithInstanceOfJavaClass.kt") + public void testComparingCallableReferencesWithInstanceOfJavaClass() throws Exception { + runTest("compiler/testData/diagnostics/tests/comparingCallableReferencesWithInstanceOfJavaClass.kt"); + } + + @Test + @TestMetadata("comparisonOfGenericInterfaceWithGenericClass.kt") + public void testComparisonOfGenericInterfaceWithGenericClass() throws Exception { + runTest("compiler/testData/diagnostics/tests/comparisonOfGenericInterfaceWithGenericClass.kt"); + } + @Test @TestMetadata("Constants.kt") public void testConstants() throws Exception { @@ -243,6 +261,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia runTest("compiler/testData/diagnostics/tests/DiamondProperty.kt"); } + @Test + @TestMetadata("differentNumericTypesFromSmartCast.kt") + public void testDifferentNumericTypesFromSmartCast() throws Exception { + runTest("compiler/testData/diagnostics/tests/differentNumericTypesFromSmartCast.kt"); + } + @Test @TestMetadata("Dollar.kt") public void testDollar() throws Exception { @@ -255,6 +279,18 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia runTest("compiler/testData/diagnostics/tests/EnumEntryAsType.kt"); } + @Test + @TestMetadata("equalityComparisonToSelf.kt") + public void testEqualityComparisonToSelf() throws Exception { + runTest("compiler/testData/diagnostics/tests/equalityComparisonToSelf.kt"); + } + + @Test + @TestMetadata("equalityWithSmartCastInIfBlock.kt") + public void testEqualityWithSmartCastInIfBlock() throws Exception { + runTest("compiler/testData/diagnostics/tests/equalityWithSmartCastInIfBlock.kt"); + } + @Test @TestMetadata("ExtensionCallInvoke.kt") public void testExtensionCallInvoke() throws Exception { @@ -10398,6 +10434,18 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia runTest("compiler/testData/diagnostics/tests/enum/enumWithEmptyName.kt"); } + @Test + @TestMetadata("equalityOfEnumAndParameter.kt") + public void testEqualityOfEnumAndParameter() throws Exception { + runTest("compiler/testData/diagnostics/tests/enum/equalityOfEnumAndParameter.kt"); + } + + @Test + @TestMetadata("equalityOfFlexibleTypeParameters.kt") + public void testEqualityOfFlexibleTypeParameters() throws Exception { + runTest("compiler/testData/diagnostics/tests/enum/equalityOfFlexibleTypeParameters.kt"); + } + @Test @TestMetadata("ExplicitConstructorCall.kt") public void testExplicitConstructorCall() throws Exception { @@ -35455,6 +35503,30 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia runTest("compiler/testData/diagnostics/testsWithStdLib/commonCollections.kt"); } + @Test + @TestMetadata("comparingDifferentSubclassesCommonInterface.kt") + public void testComparingDifferentSubclassesCommonInterface() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/comparingDifferentSubclassesCommonInterface.kt"); + } + + @Test + @TestMetadata("comparingPlatformTypes.kt") + public void testComparingPlatformTypes() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/comparingPlatformTypes.kt"); + } + + @Test + @TestMetadata("comparingSmartCastValueToBoolean.kt") + public void testComparingSmartCastValueToBoolean() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/comparingSmartCastValueToBoolean.kt"); + } + + @Test + @TestMetadata("comparingTripleWithPair.kt") + public void testComparingTripleWithPair() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/comparingTripleWithPair.kt"); + } + @Test @TestMetadata("compileTimeUnsignedArray.kt") public void testCompileTimeUnsignedArray() throws Exception { @@ -35479,6 +35551,24 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia runTest("compiler/testData/diagnostics/testsWithStdLib/enumEntryInitialization.kt"); } + @Test + @TestMetadata("equalityCompatibilityCommonCases.kt") + public void testEqualityCompatibilityCommonCases() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityCommonCases.kt"); + } + + @Test + @TestMetadata("equalityCompatibilityOldBehavior_Off.kt") + public void testEqualityCompatibilityOldBehavior_Off() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_Off.kt"); + } + + @Test + @TestMetadata("equalityCompatibilityOldBehavior_On.kt") + public void testEqualityCompatibilityOldBehavior_On() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_On.kt"); + } + @Test @TestMetadata("exitProcess.kt") public void testExitProcess() throws Exception { diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index 436fcf4a7a8..dfe7592e50c 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -1338,6 +1338,26 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { parameter("leftType") parameter("rightType") } + val INCOMPATIBLE_ENUM_COMPARISON by warning { + parameter("leftType") + parameter("rightType") + } + val FORBIDDEN_IDENTITY_EQUALS by error { + parameter("leftType") + parameter("rightType") + } + val FORBIDDEN_IDENTITY_EQUALS_WARNING by warning { + parameter("leftType") + parameter("rightType") + } + val DEPRECATED_IDENTITY_EQUALS by warning { + parameter("leftType") + parameter("rightType") + } + val IMPLICIT_BOXING_IN_IDENTITY_EQUALS by warning { + parameter("leftType") + parameter("rightType") + } val INC_DEC_SHOULD_NOT_RETURN_UNIT by error(PositioningStrategy.OPERATOR) val ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT by error(PositioningStrategy.OPERATOR) { parameter("functionSymbol") diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index d69b540d312..d2de7227d19 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -693,6 +693,11 @@ object FirErrors { val EQUALITY_NOT_APPLICABLE by error3() val EQUALITY_NOT_APPLICABLE_WARNING by warning3() val INCOMPATIBLE_ENUM_COMPARISON_ERROR by error2() + val INCOMPATIBLE_ENUM_COMPARISON by warning2() + val FORBIDDEN_IDENTITY_EQUALS by error2() + val FORBIDDEN_IDENTITY_EQUALS_WARNING by warning2() + val DEPRECATED_IDENTITY_EQUALS by warning2() + val IMPLICIT_BOXING_IN_IDENTITY_EQUALS by warning2() val INC_DEC_SHOULD_NOT_RETURN_UNIT by error0(SourceElementPositioningStrategies.OPERATOR) val ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT by error2(SourceElementPositioningStrategies.OPERATOR) val PROPERTY_AS_OPERATOR by error1(SourceElementPositioningStrategies.OPERATOR) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirEqualityCompatibilityChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirEqualityCompatibilityChecker.kt index 4f430625712..672272ee1a5 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirEqualityCompatibilityChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirEqualityCompatibilityChecker.kt @@ -5,109 +5,247 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression -import org.jetbrains.kotlin.KtRealSourceElementKind import org.jetbrains.kotlin.KtNodeTypes -import org.jetbrains.kotlin.fir.analysis.checkers.ConeTypeCompatibilityChecker -import org.jetbrains.kotlin.fir.analysis.checkers.ConeTypeCompatibilityChecker.isCompatible +import org.jetbrains.kotlin.KtRealSourceElementKind +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory2 import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.diagnostics.reportOn +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.analysis.checkers.collectUpperBounds import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass +import org.jetbrains.kotlin.fir.declarations.utils.isFinal +import org.jetbrains.kotlin.fir.declarations.utils.isInline +import org.jetbrains.kotlin.fir.declarations.utils.isInterface import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall +import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirOperation -import org.jetbrains.kotlin.fir.render -import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol +import org.jetbrains.kotlin.fir.expressions.FirSmartCastExpression +import org.jetbrains.kotlin.fir.isPrimitiveType +import org.jetbrains.kotlin.fir.resolve.fullyExpandedType +import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl +import org.jetbrains.kotlin.name.StandardClassIds +import org.jetbrains.kotlin.text +import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty object FirEqualityCompatibilityChecker : FirEqualityOperatorCallChecker() { override fun check(expression: FirEqualityOperatorCall, context: CheckerContext, reporter: DiagnosticReporter) { val arguments = expression.argumentList.arguments - if (arguments.size != 2) return - val lType = arguments[0].typeRef.coneType - val rType = arguments[1].typeRef.coneType - checkCompatibility(lType, rType, context, expression, reporter) - checkSensibleness(lType, rType, context, expression, reporter) - } + require(arguments.size == 2) { "Equality operator call with non-2 arguments" } - private fun checkCompatibility( - lType: ConeKotlinType, - rType: ConeKotlinType, - context: CheckerContext, - expression: FirEqualityOperatorCall, - reporter: DiagnosticReporter - ) { - // If one of the type is already `Nothing?`, we skip reporting further comparison. This is to allow comparing with `null`, which has - // type `Nothing?` - if (lType.isNullableNothing || rType.isNullableNothing) return - val inferenceContext = context.session.typeContext + val l = arguments[0].toArgumentInfo(context) + val r = arguments[1].toArgumentInfo(context) - val compatibility = try { - inferenceContext.isCompatible(lType, rType) - } catch (e: Throwable) { - throw IllegalStateException( - "Exception while determining type compatibility: lType: $lType, rType: $rType, " + - "equality ${expression.render()}, " + - "file ${context.containingFile?.name}", - e + checkSenselessness(l.smartCastType, r.smartCastType, context, expression, reporter) + + val checkApplicability = when (expression.operation) { + FirOperation.EQ, FirOperation.NOT_EQ -> ::checkEqualityApplicability + FirOperation.IDENTITY, FirOperation.NOT_IDENTITY -> ::checkIdentityApplicability + else -> error("Invalid operator of FirEqualityOperatorCall") + } + + checkApplicability(l.originalTypeInfo, r.originalTypeInfo, context).ifInapplicable { + // Ideally this should match cases when K1 + // sees a non-empty intersection and none of the + // types is an enum, but intersections in K1 + // work differently from intersections in K2. + val isCaseMissedByK1 = it != Applicability.INAPPLICABLE_AS_ENUMS + && l.originalTypeInfo.isLiterallyTypeParameter + && r.originalTypeInfo.isLiterallyTypeParameter + val replicateK1Behavior = !context.languageVersionSettings.supportsFeature(LanguageFeature.ReportErrorsForComparisonOperators) + + return reporter.reportInapplicabilityDiagnostic( + expression, it, expression.operation, forceWarning = isCaseMissedByK1 && replicateK1Behavior, + l.originalTypeInfo, r.originalTypeInfo, + l.userType, r.userType, context, ) } - if (compatibility != ConeTypeCompatibilityChecker.Compatibility.COMPATIBLE) { - when (expression.source?.kind) { - KtRealSourceElementKind -> { - // Note: FE1.0 reports INCOMPATIBLE_ENUM_COMPARISON_ERROR only when TypeIntersector.isIntersectionEmpty() thinks the - // given types are compatible. Exactly mimicking the behavior of FE1.0 is difficult and does not seem to provide any - // value. So instead, we deterministically output INCOMPATIBLE_ENUM_COMPARISON_ERROR if at least one of the value is an - // enum. - if (compatibility == ConeTypeCompatibilityChecker.Compatibility.HARD_INCOMPATIBLE && - (lType.isEnumType(context) || rType.isEnumType(context)) - ) { - reporter.reportOn( - expression.source, - FirErrors.INCOMPATIBLE_ENUM_COMPARISON_ERROR, - lType, - rType, - context - ) - } else { - reporter.reportOn( - expression.source, - if (compatibility == ConeTypeCompatibilityChecker.Compatibility.HARD_INCOMPATIBLE) { - FirErrors.EQUALITY_NOT_APPLICABLE - } else { - FirErrors.EQUALITY_NOT_APPLICABLE_WARNING - }, - expression.operation.operator, - lType, - rType, - context - ) - } - } - else -> reporter.reportOn( - expression.source, - if (compatibility == ConeTypeCompatibilityChecker.Compatibility.HARD_INCOMPATIBLE) { - FirErrors.INCOMPATIBLE_TYPES - } else { - FirErrors.INCOMPATIBLE_TYPES_WARNING - }, - lType, - rType, - context - ) - } + + if (l.argument !is FirSmartCastExpression && r.argument !is FirSmartCastExpression) { + return + } + + checkApplicability(l.smartCastTypeInfo, r.smartCastTypeInfo, context).ifInapplicable { + return reporter.reportInapplicabilityDiagnostic( + expression, it, expression.operation, forceWarning = true, + l.smartCastTypeInfo, r.smartCastTypeInfo, + l.userType, r.userType, context, + ) } } - private fun ConeKotlinType.isEnumType( - context: CheckerContext - ): Boolean { - if (isEnum) return true - val firRegularClassSymbol = (this as? ConeClassLikeType)?.lookupTag?.toFirRegularClassSymbol(context.session) ?: return false - return firRegularClassSymbol.isEnumClass + private fun checkEqualityApplicability(l: TypeInfo, r: TypeInfo, context: CheckerContext): Applicability { + val oneIsBuiltin = l.isBuiltin || r.isBuiltin + + // The compiler should only check comparisons + // when builtins are involved. + // Builtins' supertypes must not be present in + // the list of special fqNames described in RULES1 + + return when { + oneIsBuiltin && shouldReportAsPerRules1(l, r, context) -> getInapplicabilityFor(l, r) + else -> Applicability.APPLICABLE + } } - private fun checkSensibleness( + private fun checkIdentityApplicability(l: TypeInfo, r: TypeInfo, context: CheckerContext): Applicability { + // The compiler should only check comparisons + // when identity-less types or builtins are involved. + + val oneIsBuiltin = l.isBuiltin || r.isBuiltin + val oneIsNotNull = !l.type.isNullable || !r.type.isNullable + + return when { + l.isIdentityLess || r.isIdentityLess -> Applicability.INAPPLICABLE_AS_IDENTITY_LESS + oneIsBuiltin && oneIsNotNull && shouldReportAsPerRules1(l, r, context) -> getInapplicabilityFor(l, r) + else -> Applicability.APPLICABLE + } + } + + private fun getInapplicabilityFor(l: TypeInfo, r: TypeInfo): Applicability { + val isIntersectionEmpty = l.enforcesEmptyIntersection || r.enforcesEmptyIntersection + val isOneEnum = l.isEnumClass || r.isEnumClass + + return when { + !isIntersectionEmpty && isOneEnum -> Applicability.INAPPLICABLE_AS_ENUMS + else -> Applicability.GENERALLY_INAPPLICABLE + } + } + + private fun shouldReportAsPerRules1(l: TypeInfo, r: TypeInfo, context: CheckerContext): Boolean { + // Builtins are always final classes, so + // we only need to check if one is related + // to the other + + fun TypeInfo.isSubclassOf(other: TypeInfo) = when { + other.enforcesEmptyIntersection -> type.classId == other.type.classId + else -> notNullType.isSubtypeOf(other.notNullType, context.session) + } + + return when { + l.type.isNothingOrNullableNothing || r.type.isNothingOrNullableNothing -> false + else -> !l.isSubclassOf(r) && !r.isSubclassOf(l) + } + } + + private enum class Applicability { + APPLICABLE, + GENERALLY_INAPPLICABLE, + INAPPLICABLE_AS_ENUMS, + INAPPLICABLE_AS_IDENTITY_LESS, + } + + private inline fun Applicability.ifInapplicable(block: (Applicability) -> Unit) = when (this) { + Applicability.APPLICABLE -> {} + else -> block(this) + } + + private fun getGeneralInapplicabilityDiagnostic(forceWarning: Boolean) = when { + forceWarning -> FirErrors.EQUALITY_NOT_APPLICABLE_WARNING + else -> FirErrors.EQUALITY_NOT_APPLICABLE + } + + private fun getIdentityLessInapplicabilityDiagnostic( + l: TypeInfo, + r: TypeInfo, + forceWarning: Boolean, + context: CheckerContext, + ): KtDiagnosticFactory2 { + val areBothPrimitives = l.isPrimitive && r.isPrimitive + val areSameTypes = l.type.classId == r.type.classId + val shouldProperlyReportError = context.languageVersionSettings.supportsFeature(LanguageFeature.ReportErrorsForComparisonOperators) + + // In this case K1 reports nothing + val shouldRelaxDiagnostic = (l.type.isNullableNothing || r.type.isNullableNothing) && !shouldProperlyReportError + + return when { + // See: KT-28252 + areSameTypes && areBothPrimitives -> FirErrors.DEPRECATED_IDENTITY_EQUALS + // The same reason as above + isIdentityComparedWithImplicitBoxing(l, r, context.session) -> FirErrors.IMPLICIT_BOXING_IN_IDENTITY_EQUALS + forceWarning || shouldRelaxDiagnostic -> FirErrors.FORBIDDEN_IDENTITY_EQUALS_WARNING + else -> FirErrors.FORBIDDEN_IDENTITY_EQUALS + } + } + + private fun isIdentityComparedWithImplicitBoxing(l: TypeInfo, r: TypeInfo, session: FirSession) = + isPrimitiveWithNonPrimitiveSupertype(l, r, session) || isPrimitiveWithNonPrimitiveSupertype(r, l, session) + + private fun isPrimitiveWithNonPrimitiveSupertype(l: TypeInfo, r: TypeInfo, session: FirSession) = + l.isPrimitive && !r.isPrimitive && l.type.isSubtypeOf(r.type, session) + + private fun getSourceLessInapplicabilityDiagnostic(forceWarning: Boolean) = when { + forceWarning -> FirErrors.INCOMPATIBLE_TYPES_WARNING + else -> FirErrors.INCOMPATIBLE_TYPES + } + + private fun getEnumInapplicabilityDiagnostic( + l: TypeInfo, + r: TypeInfo, + forceWarning: Boolean, + context: CheckerContext, + ): KtDiagnosticFactory2 { + // Preserving the behavior on the old test data + // simplifies detecting fir-differences, + // which is crucial for this checker + val isOldTestData = !context.languageVersionSettings.supportsFeature( + LanguageFeature.ProhibitComparisonOfIncompatibleEnums, + ) + + // In this corner case K1 reports nothing + val bothNullableEnums = l.isNullableEnum && r.isNullableEnum + // When comparing enums, for type parameters K1 + // tries to pick the "representative" superclass + // instead of the proper intersection. + // We can't guarantee that in such cases + // K2 reports the same as K1 + val areIntersectionsInvolved = l.type is ConeIntersectionType || r.type is ConeIntersectionType + + val shouldProperlyReportError = context.languageVersionSettings.supportsFeature(LanguageFeature.ReportErrorsForComparisonOperators) + val shouldRelaxDiagnostic = (bothNullableEnums || areIntersectionsInvolved) && !shouldProperlyReportError + + return when { + forceWarning || isOldTestData || shouldRelaxDiagnostic -> FirErrors.INCOMPATIBLE_ENUM_COMPARISON + else -> FirErrors.INCOMPATIBLE_ENUM_COMPARISON_ERROR + } + } + + private fun DiagnosticReporter.reportInapplicabilityDiagnostic( + expression: FirEqualityOperatorCall, + applicability: Applicability, + operation: FirOperation, + forceWarning: Boolean, + l: TypeInfo, + r: TypeInfo, + lUserType: ConeKotlinType, + rUserType: ConeKotlinType, + context: CheckerContext, + ): Unit = when { + applicability == Applicability.INAPPLICABLE_AS_IDENTITY_LESS -> reportOn( + expression.source, getIdentityLessInapplicabilityDiagnostic(l, r, forceWarning, context), + lUserType, rUserType, context, + ) + applicability == Applicability.INAPPLICABLE_AS_ENUMS -> reportOn( + expression.source, getEnumInapplicabilityDiagnostic(l, r, forceWarning, context), + lUserType, rUserType, context, + ) + // This check ensures K2 reports the same diagnostics as K1 used to. + expression.source?.kind !is KtRealSourceElementKind -> reportOn( + expression.source, getSourceLessInapplicabilityDiagnostic(forceWarning), + lUserType, rUserType, context, + ) + applicability == Applicability.GENERALLY_INAPPLICABLE -> reportOn( + expression.source, getGeneralInapplicabilityDiagnostic(forceWarning), + operation.operator, lUserType, rUserType, context, + ) + else -> error("Shouldn't be here") + } + + private fun checkSenselessness( lType: ConeKotlinType, rType: ConeKotlinType, context: CheckerContext, @@ -139,3 +277,83 @@ object FirEqualityCompatibilityChecker : FirEqualityOperatorCallChecker() { } } } + +private class TypeInfo( + val type: ConeKotlinType, + val notNullType: ConeKotlinType, + val isFinalClass: Boolean, + val isEnumClass: Boolean, + val isPrimitive: Boolean, + val isBuiltin: Boolean, + val isValueClass: Boolean, + val isLiterallyTypeParameter: Boolean, +) { + override fun toString() = "$type" +} + +private val FirClassSymbol<*>.isBuiltin get() = isPrimitiveType() || classId == StandardClassIds.String || isEnumClass + +// This property is used to replicate K1 behavior, and it +// tries to predict empty intersections from the K1 point-of-view. +// Enum classes are final, but enum entries are their subclasses. +private val TypeInfo.enforcesEmptyIntersection get() = isFinalClass && !isEnumClass + +private val TypeInfo.isNullableEnum get() = isEnumClass && type.isNullable + +private val TypeInfo.isIdentityLess get() = isPrimitive || !type.isNullable && isValueClass + +private val FirClassSymbol<*>.isFinalClass get() = isClass && isFinal + +// NB: This is what RULES1 means then it says "class". +private val FirClassSymbol<*>.isClass get() = !isInterface + +private fun ConeKotlinType.toTypeInfo(session: FirSession): TypeInfo { + val bounds = collectUpperBounds().map { type -> toKotlinType(type).replaceArgumentsWithStarProjections() } + val type = bounds.ifNotEmpty { ConeTypeIntersector.intersectTypes(session.typeContext, this) } + ?: session.builtinTypes.nullableAnyType.type + val notNullType = type.withNullability(ConeNullability.NOT_NULL, session.typeContext) + + return TypeInfo( + type, notNullType, + isFinalClass = bounds.any { it.toClassSymbol(session)?.isFinalClass == true }, + isEnumClass = bounds.any { it.toClassSymbol(session)?.isEnumClass == true }, + isPrimitive = bounds.any { it.isPrimitive }, + isBuiltin = bounds.any { it.toClassSymbol(session)?.isBuiltin == true }, + isValueClass = bounds.any { it.toClassSymbol(session)?.isInline == true }, + isLiterallyTypeParameter = this.lowerBoundIfFlexible() is ConeTypeParameterType, + ) +} + +private fun toKotlinType(type: ConeClassLikeType): ConeClassLikeType { + // Type arguments are ignored by design + return ConeClassLikeTypeImpl(type.lookupTag, type.typeArguments, type.isNullable) +} + +private class ArgumentInfo( + val argument: FirExpression, + val userType: ConeKotlinType, + val originalType: ConeKotlinType, + val session: FirSession, +) { + val smartCastType: ConeKotlinType by lazy { + if (argument !is FirSmartCastExpression) originalType else userType.fullyExpandedType(session) + } + + val originalTypeInfo get() = originalType.toTypeInfo(session) + + val smartCastTypeInfo get() = smartCastType.toTypeInfo(session) + + override fun toString() = "${argument.source?.text} :: $userType" +} + +@Suppress("RecursivePropertyAccessor") +private val FirExpression.mostOriginalTypeIfSmartCast: ConeKotlinType + get() = when (this) { + is FirSmartCastExpression -> originalExpression.mostOriginalTypeIfSmartCast + else -> typeRef.coneType + } + +private fun FirExpression.toArgumentInfo(context: CheckerContext) = + ArgumentInfo( + this, typeRef.coneType, mostOriginalTypeIfSmartCast.fullyExpandedType(context.session), context.session, + ) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt index 13b741426e4..4e9be4cbbf5 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt @@ -221,7 +221,10 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FINAL_UPPER_BOUND import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FLOAT_LITERAL_OUT_OF_RANGE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DEPRECATED_BINARY_MOD import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_PROPERTY_TYPE_IN_CONSTRUCTOR +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DEPRECATED_IDENTITY_EQUALS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FORBIDDEN_BINARY_MOD +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FORBIDDEN_IDENTITY_EQUALS +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FORBIDDEN_IDENTITY_EQUALS_WARNING import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FORBIDDEN_VARARG_PARAMETER_TYPE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUNCTION_CALL_EXPECTED import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUNCTION_DECLARATION_WITH_NO_NAME @@ -249,6 +252,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_SUSPEND_F import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_SUSPEND_PROPERTY_ACCESS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_UNDERSCORE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.IMPLEMENTATION_BY_DELEGATION_IN_EXPECT_CLASS +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.IMPLICIT_BOXING_IN_IDENTITY_EQUALS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.IMPLICIT_NOTHING_PROPERTY_TYPE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.IMPLICIT_NOTHING_RETURN_TYPE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_CANDIDATE @@ -262,6 +266,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_TARG import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_TARGET_PROPERTY_HAS_NO_BACKING_FIELD import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_TARGET_PROPERTY_HAS_NO_DELEGATE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCOMPATIBLE_ENUM_COMPARISON import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCOMPATIBLE_ENUM_COMPARISON_ERROR import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCOMPATIBLE_MODIFIERS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCOMPATIBLE_TYPES @@ -2002,6 +2007,36 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() { RENDER_TYPE, RENDER_TYPE ) + map.put( + INCOMPATIBLE_ENUM_COMPARISON, + "Comparison of incompatible enums ''{0}'' and ''{1}'' is always unsuccessful", + RENDER_TYPE, + RENDER_TYPE + ) + map.put( + FORBIDDEN_IDENTITY_EQUALS, + "Identity equality for arguments of types {0} and {1} is forbidden", + RENDER_TYPE, + RENDER_TYPE + ) + map.put( + FORBIDDEN_IDENTITY_EQUALS_WARNING, + "Identity equality for arguments of types {0} and {1} is forbidden", + RENDER_TYPE, + RENDER_TYPE + ) + map.put( + DEPRECATED_IDENTITY_EQUALS, + "Identity equality for arguments of types {0} and {1} is deprecated", + RENDER_TYPE, + RENDER_TYPE + ) + map.put( + IMPLICIT_BOXING_IN_IDENTITY_EQUALS, + "Identity equality for arguments of types {0} and {1} can be unstable because of implicit boxing", + RENDER_TYPE, + RENDER_TYPE + ) map.put(INC_DEC_SHOULD_NOT_RETURN_UNIT, "Functions inc(), dec() shouldn't return Unit to be used by operators ++, --") map.put( ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT, 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 7b86f774b07..3c6a57910e0 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 @@ -23,10 +23,7 @@ import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag -import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol +import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef @@ -607,6 +604,10 @@ fun ConeKotlinType.toRegularClassSymbol(session: FirSession): FirRegularClassSym return (this as? ConeClassLikeType)?.toRegularClassSymbol(session) } +fun ConeClassLikeType.toClassSymbol(session: FirSession): FirClassSymbol<*>? { + return fullyExpandedType(session).toSymbol(session) as? FirClassSymbol<*> +} + private fun lowerThanBound(context: ConeInferenceContext, argument: ConeKotlinType, typeParameterSymbol: FirTypeParameterSymbol): Boolean { typeParameterSymbol.resolvedBounds.forEach { boundTypeRef -> if (argument != boundTypeRef.coneType && argument.isSubtypeOf(context, boundTypeRef.coneType)) { diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/utils/FirSymbolStatusUtils.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/utils/FirSymbolStatusUtils.kt index 40c6271518f..075236c527e 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/utils/FirSymbolStatusUtils.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/utils/FirSymbolStatusUtils.kt @@ -83,12 +83,18 @@ inline val FirClassSymbol<*>.isLocalClassOrAnonymousObject: Boolean get() = classId.isLocal || this is FirAnonymousObjectSymbol +inline val FirClassSymbol<*>.isClass: Boolean + get() = classKind.isClass + inline val FirClassSymbol<*>.isInterface: Boolean get() = classKind.isInterface inline val FirClassSymbol<*>.isEnumClass: Boolean get() = classKind.isEnumClass +inline val FirClassSymbol<*>.isEnumEntry: Boolean + get() = classKind.isEnumEntry + // ---------------------- specific callables ---------------------- inline val FirPropertyAccessorSymbol.allowsToHaveFakeOverride: Boolean get() = visibility.allowsToHaveFakeOverride diff --git a/compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/byteOperations.kt b/compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/byteOperations.kt index bd336fc1126..e66ee3e9309 100644 --- a/compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/byteOperations.kt +++ b/compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/byteOperations.kt @@ -1,7 +1,7 @@ // TARGET_BACKEND: JVM_IR // TARGET_BACKEND: NATIVE // TARGET_BACKEND: JS_IR -// IGNORE_BACKEND_K1: JVM_IR, NATIVE, JS_IR, JS_IR_ES6 +// IGNORE_BACKEND_K1: NATIVE const val minusOneVal = (-1).toByte() const val oneVal = 1.toByte() @@ -106,16 +106,16 @@ fun box(): String { if (plus3 != 5) return "Fail 2.3" if (plus4 != 4) return "Fail 2.4" if (plus5 != 4) return "Fail 2.5" - if (plus6 != 4) return "Fail 2.6" + if (plus6 != 4L) return "Fail 2.6" if (plus7 != 4.0f) return "Fail 2.7" - if (plus8 != 4.0f) return "Fail 2.8" + if (plus8 != 4.0) return "Fail 2.8" if (minus1 != -1) return "Fail 3.1" if (minus2 != 0) return "Fail 3.2" if (minus3 != 1) return "Fail 3.3" if (minus4 != 0) return "Fail 3.4" if (minus5 != 0) return "Fail 3.5" - if (minus6 != 0) return "Fail 3.6" + if (minus6 != 0L) return "Fail 3.6" if (minus7 != 0.0f) return "Fail 3.7" if (minus8 != 0.0) return "Fail 3.8" @@ -124,7 +124,7 @@ fun box(): String { if (times3 != 6) return "Fail 4.3" if (times4 != 4) return "Fail 4.4" if (times5 != 4) return "Fail 4.5" - if (times6 != 4) return "Fail 4.6" + if (times6 != 4L) return "Fail 4.6" if (times7 != 4.0f) return "Fail 4.7" if (times8 != 4.0) return "Fail 4.8" @@ -133,7 +133,7 @@ fun box(): String { if (div3 != 1) return "Fail 5.3" if (div4 != 1) return "Fail 5.4" if (div5 != 1) return "Fail 5.5" - if (div6 != 1) return "Fail 5.6" + if (div6 != 1L) return "Fail 5.6" if (div7 != 1.0f) return "Fail 5.7" if (div8 != 1.0) return "Fail 5.8" @@ -142,7 +142,7 @@ fun box(): String { if (rem3 != 1) return "Fail 6.3" if (rem4 != 0) return "Fail 6.4" if (rem5 != 0) return "Fail 6.5" - if (rem6 != 0) return "Fail 6.6" + if (rem6 != 0L) return "Fail 6.6" if (rem7 != 0.0f) return "Fail 6.7" if (rem8 != 0.0) return "Fail 6.8" @@ -151,11 +151,11 @@ fun box(): String { if (unaryMinus1 != -1) return "Fail 7.3" if (unaryMinus2 != 1) return "Fail 7.4" - if (convert1 != 1) return "Fail 8.1" + if (convert1 != 1.toByte()) return "Fail 8.1" if (convert2 != '') return "Fail 8.2" - if (convert3 != 1) return "Fail 8.3" + if (convert3 != 1.toShort()) return "Fail 8.3" if (convert4 != 1) return "Fail 8.4" - if (convert5 != 1) return "Fail 8.5" + if (convert5 != 1L) return "Fail 8.5" if (convert6 != 1.0f) return "Fail 8.6" if (convert7 != 1.0) return "Fail 8.7" diff --git a/compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/doubleOperations.kt b/compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/doubleOperations.kt index 190c7aea1c3..22b5c05f05b 100644 --- a/compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/doubleOperations.kt +++ b/compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/doubleOperations.kt @@ -1,7 +1,7 @@ // TARGET_BACKEND: JVM_IR // TARGET_BACKEND: NATIVE // TARGET_BACKEND: JS_IR -// IGNORE_BACKEND_K1: JVM_IR, NATIVE, JS_IR, JS_IR_ES6 +// IGNORE_BACKEND_K1: NATIVE const val minusOneVal = -1.0 const val oneVal = 1.0 @@ -101,59 +101,59 @@ fun box(): String { if (compareTo7 != 0) return "Fail 1.7" if (compareTo8 != 0) return "Fail 1.8" - if (plus1 != 3) return "Fail 2.1" - if (plus2 != 4) return "Fail 2.2" - if (plus3 != 5) return "Fail 2.3" - if (plus4 != 4) return "Fail 2.4" - if (plus5 != 4) return "Fail 2.5" - if (plus6 != 4) return "Fail 2.6" - if (plus7 != 4.0f) return "Fail 2.7" + if (plus1 != 3.0) return "Fail 2.1" + if (plus2 != 4.0) return "Fail 2.2" + if (plus3 != 5.0) return "Fail 2.3" + if (plus4 != 4.0) return "Fail 2.4" + if (plus5 != 4.0) return "Fail 2.5" + if (plus6 != 4.0) return "Fail 2.6" + if (plus7 != 4.0) return "Fail 2.7" if (plus8 != 4.0) return "Fail 2.8" - if (minus1 != -1) return "Fail 3.1" - if (minus2 != 0) return "Fail 3.2" - if (minus3 != 1) return "Fail 3.3" - if (minus4 != 0) return "Fail 3.4" - if (minus5 != 0) return "Fail 3.5" - if (minus6 != 0) return "Fail 3.6" - if (minus7 != 0.0f) return "Fail 3.7" + if (minus1 != -1.0) return "Fail 3.1" + if (minus2 != 0.0) return "Fail 3.2" + if (minus3 != 1.0) return "Fail 3.3" + if (minus4 != 0.0) return "Fail 3.4" + if (minus5 != 0.0) return "Fail 3.5" + if (minus6 != 0.0) return "Fail 3.6" + if (minus7 != 0.0) return "Fail 3.7" if (minus8 != 0.0) return "Fail 3.8" - if (times1 != 2) return "Fail 4.1" - if (times2 != 4) return "Fail 4.2" - if (times3 != 6) return "Fail 4.3" - if (times4 != 4) return "Fail 4.4" - if (times5 != 4) return "Fail 4.5" - if (times6 != 4) return "Fail 4.6" - if (times7 != 4.0f) return "Fail 4.7" + if (times1 != 2.0) return "Fail 4.1" + if (times2 != 4.0) return "Fail 4.2" + if (times3 != 6.0) return "Fail 4.3" + if (times4 != 4.0) return "Fail 4.4" + if (times5 != 4.0) return "Fail 4.5" + if (times6 != 4.0) return "Fail 4.6" + if (times7 != 4.0) return "Fail 4.7" if (times8 != 4.0) return "Fail 4.8" if (div1 != 0.5) return "Fail 5.1" if (div2 != 1.0) return "Fail 5.2" if (div3 != 1.5) return "Fail 5.3" - if (div4 != 1) return "Fail 5.4" - if (div5 != 1) return "Fail 5.5" - if (div6 != 1) return "Fail 5.6" - if (div7 != 1.0f) return "Fail 5.7" + if (div4 != 1.0) return "Fail 5.4" + if (div5 != 1.0) return "Fail 5.5" + if (div6 != 1.0) return "Fail 5.6" + if (div7 != 1.0) return "Fail 5.7" if (div8 != 1.0) return "Fail 5.8" - if (rem1 != 1) return "Fail 6.1" - if (rem2 != 0) return "Fail 6.2" - if (rem3 != 1) return "Fail 6.3" - if (rem4 != 0) return "Fail 6.4" - if (rem5 != 0) return "Fail 6.5" - if (rem6 != 0) return "Fail 6.6" - if (rem7 != 0.0f) return "Fail 6.7" + if (rem1 != 1.0) return "Fail 6.1" + if (rem2 != 0.0) return "Fail 6.2" + if (rem3 != 1.0) return "Fail 6.3" + if (rem4 != 0.0) return "Fail 6.4" + if (rem5 != 0.0) return "Fail 6.5" + if (rem6 != 0.0) return "Fail 6.6" + if (rem7 != 0.0) return "Fail 6.7" if (rem8 != 0.0) return "Fail 6.8" - if (unaryPlus1 != 1) return "Fail 7.1" - if (unaryPlus2 != -1) return "Fail 7.2" - if (unaryMinus1 != -1) return "Fail 7.3" - if (unaryMinus2 != 1) return "Fail 7.4" + if (unaryPlus1 != 1.0) return "Fail 7.1" + if (unaryPlus2 != -1.0) return "Fail 7.2" + if (unaryMinus1 != -1.0) return "Fail 7.3" + if (unaryMinus2 != 1.0) return "Fail 7.4" if (convert1 != '') return "Fail 8.1" if (convert2 != 1) return "Fail 8.2" - if (convert3 != 1) return "Fail 8.3" + if (convert3 != 1L) return "Fail 8.3" if (convert4 != 1.0f) return "Fail 8.4" if (convert5 != 1.0) return "Fail 8.5" diff --git a/compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/floatOperations.kt b/compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/floatOperations.kt index b503c6d9001..103d91beeb3 100644 --- a/compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/floatOperations.kt +++ b/compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/floatOperations.kt @@ -1,7 +1,7 @@ // TARGET_BACKEND: JVM_IR // TARGET_BACKEND: NATIVE // TARGET_BACKEND: JS_IR -// IGNORE_BACKEND_K1: JVM_IR, NATIVE, JS_IR, JS_IR_ES6 +// IGNORE_BACKEND_K1: NATIVE const val minusOneVal = -1.0f const val oneVal = 1.0f @@ -101,59 +101,59 @@ fun box(): String { if (compareTo7 != 0) return "Fail 1.7" if (compareTo8 != 0) return "Fail 1.8" - if (plus1 != 3) return "Fail 2.1" - if (plus2 != 4) return "Fail 2.2" - if (plus3 != 5) return "Fail 2.3" - if (plus4 != 4) return "Fail 2.4" - if (plus5 != 4) return "Fail 2.5" - if (plus6 != 4) return "Fail 2.6" + if (plus1 != 3f) return "Fail 2.1" + if (plus2 != 4f) return "Fail 2.2" + if (plus3 != 5f) return "Fail 2.3" + if (plus4 != 4f) return "Fail 2.4" + if (plus5 != 4f) return "Fail 2.5" + if (plus6 != 4f) return "Fail 2.6" if (plus7 != 4.0f) return "Fail 2.7" if (plus8 != 4.0) return "Fail 2.8" - if (minus1 != -1) return "Fail 3.1" - if (minus2 != 0) return "Fail 3.2" - if (minus3 != 1) return "Fail 3.3" - if (minus4 != 0) return "Fail 3.4" - if (minus5 != 0) return "Fail 3.5" - if (minus6 != 0) return "Fail 3.6" + if (minus1 != -1f) return "Fail 3.1" + if (minus2 != 0f) return "Fail 3.2" + if (minus3 != 1f) return "Fail 3.3" + if (minus4 != 0f) return "Fail 3.4" + if (minus5 != 0f) return "Fail 3.5" + if (minus6 != 0f) return "Fail 3.6" if (minus7 != 0.0f) return "Fail 3.7" if (minus8 != 0.0) return "Fail 3.8" - if (times1 != 2) return "Fail 4.1" - if (times2 != 4) return "Fail 4.2" - if (times3 != 6) return "Fail 4.3" - if (times4 != 4) return "Fail 4.4" - if (times5 != 4) return "Fail 4.5" - if (times6 != 4) return "Fail 4.6" + if (times1 != 2f) return "Fail 4.1" + if (times2 != 4f) return "Fail 4.2" + if (times3 != 6f) return "Fail 4.3" + if (times4 != 4f) return "Fail 4.4" + if (times5 != 4f) return "Fail 4.5" + if (times6 != 4f) return "Fail 4.6" if (times7 != 4.0f) return "Fail 4.7" if (times8 != 4.0) return "Fail 4.8" if (div1 != 0.5f) return "Fail 5.1" if (div2 != 1.0f) return "Fail 5.2" if (div3 != 1.5f) return "Fail 5.3" - if (div4 != 1) return "Fail 5.4" - if (div5 != 1) return "Fail 5.5" - if (div6 != 1) return "Fail 5.6" + if (div4 != 1f) return "Fail 5.4" + if (div5 != 1f) return "Fail 5.5" + if (div6 != 1f) return "Fail 5.6" if (div7 != 1.0f) return "Fail 5.7" if (div8 != 1.0) return "Fail 5.8" - if (rem1 != 1) return "Fail 6.1" - if (rem2 != 0) return "Fail 6.2" - if (rem3 != 1) return "Fail 6.3" - if (rem4 != 0) return "Fail 6.4" - if (rem5 != 0) return "Fail 6.5" - if (rem6 != 0) return "Fail 6.6" + if (rem1 != 1f) return "Fail 6.1" + if (rem2 != 0f) return "Fail 6.2" + if (rem3 != 1f) return "Fail 6.3" + if (rem4 != 0f) return "Fail 6.4" + if (rem5 != 0f) return "Fail 6.5" + if (rem6 != 0f) return "Fail 6.6" if (rem7 != 0.0f) return "Fail 6.7" if (rem8 != 0.0) return "Fail 6.8" - if (unaryPlus1 != 1) return "Fail 7.1" - if (unaryPlus2 != -1) return "Fail 7.2" - if (unaryMinus1 != -1) return "Fail 7.3" - if (unaryMinus2 != 1) return "Fail 7.4" + if (unaryPlus1 != 1f) return "Fail 7.1" + if (unaryPlus2 != -1f) return "Fail 7.2" + if (unaryMinus1 != -1f) return "Fail 7.3" + if (unaryMinus2 != 1f) return "Fail 7.4" if (convert1 != '') return "Fail 8.1" if (convert2 != 1) return "Fail 8.2" - if (convert3 != 1) return "Fail 8.3" + if (convert3 != 1L) return "Fail 8.3" if (convert4 != 1.0f) return "Fail 8.4" if (convert5 != 1.0) return "Fail 8.5" diff --git a/compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/intOperations.kt b/compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/intOperations.kt index 8408404a9d2..6962e089cd8 100644 --- a/compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/intOperations.kt +++ b/compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/intOperations.kt @@ -1,7 +1,7 @@ // TARGET_BACKEND: JVM_IR // TARGET_BACKEND: NATIVE // TARGET_BACKEND: JS_IR -// IGNORE_BACKEND_K1: JVM_IR, NATIVE, JS_IR, JS_IR_ES6 +// IGNORE_BACKEND_K1: NATIVE const val minusOneVal = -1 const val oneVal = 1 @@ -106,7 +106,7 @@ fun box(): String { if (plus3 != 5) return "Fail 2.3" if (plus4 != 4) return "Fail 2.4" if (plus5 != 4) return "Fail 2.5" - if (plus6 != 4) return "Fail 2.6" + if (plus6 != 4L) return "Fail 2.6" if (plus7 != 4.0f) return "Fail 2.7" if (plus8 != 4.0) return "Fail 2.8" @@ -115,7 +115,7 @@ fun box(): String { if (minus3 != 1) return "Fail 3.3" if (minus4 != 0) return "Fail 3.4" if (minus5 != 0) return "Fail 3.5" - if (minus6 != 0) return "Fail 3.6" + if (minus6 != 0L) return "Fail 3.6" if (minus7 != 0.0f) return "Fail 3.7" if (minus8 != 0.0) return "Fail 3.8" @@ -124,7 +124,7 @@ fun box(): String { if (times3 != 6) return "Fail 4.3" if (times4 != 4) return "Fail 4.4" if (times5 != 4) return "Fail 4.5" - if (times6 != 4) return "Fail 4.6" + if (times6 != 4L) return "Fail 4.6" if (times7 != 4.0f) return "Fail 4.7" if (times8 != 4.0) return "Fail 4.8" @@ -133,7 +133,7 @@ fun box(): String { if (div3 != 1) return "Fail 5.3" if (div4 != 1) return "Fail 5.4" if (div5 != 1) return "Fail 5.5" - if (div6 != 1) return "Fail 5.6" + if (div6 != 1L) return "Fail 5.6" if (div7 != 1.0f) return "Fail 5.7" if (div8 != 1.0) return "Fail 5.8" @@ -142,7 +142,7 @@ fun box(): String { if (rem3 != 1) return "Fail 6.3" if (rem4 != 0) return "Fail 6.4" if (rem5 != 0) return "Fail 6.5" - if (rem6 != 0) return "Fail 6.6" + if (rem6 != 0L) return "Fail 6.6" if (rem7 != 0.0f) return "Fail 6.7" if (rem8 != 0.0) return "Fail 6.8" @@ -151,11 +151,11 @@ fun box(): String { if (unaryMinus1 != -1) return "Fail 7.3" if (unaryMinus2 != 1) return "Fail 7.4" - if (convert1 != 1) return "Fail 8.1" + if (convert1 != 1.toByte()) return "Fail 8.1" if (convert2 != '') return "Fail 8.2" - if (convert3 != 1) return "Fail 8.3" + if (convert3 != 1.toShort()) return "Fail 8.3" if (convert4 != 1) return "Fail 8.4" - if (convert5 != 1) return "Fail 8.5" + if (convert5 != 1L) return "Fail 8.5" if (convert6 != 1.0f) return "Fail 8.6" if (convert7 != 1.0) return "Fail 8.7" diff --git a/compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/longOperations.kt b/compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/longOperations.kt index cb3749fae7d..0e57d576d38 100644 --- a/compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/longOperations.kt +++ b/compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/longOperations.kt @@ -1,7 +1,7 @@ // TARGET_BACKEND: JVM_IR // TARGET_BACKEND: NATIVE // TARGET_BACKEND: JS_IR -// IGNORE_BACKEND_K1: JVM_IR, NATIVE, JS_IR, JS_IR_ES6 +// IGNORE_BACKEND_K1: NATIVE const val minusOneVal = -1L const val oneVal = 1L @@ -101,61 +101,61 @@ fun box(): String { if (compareTo7 != 0) return "Fail 1.7" if (compareTo8 != 0) return "Fail 1.8" - if (plus1 != 3) return "Fail 2.1" - if (plus2 != 4) return "Fail 2.2" - if (plus3 != 5) return "Fail 2.3" - if (plus4 != 4) return "Fail 2.4" - if (plus5 != 4) return "Fail 2.5" - if (plus6 != 4) return "Fail 2.6" + if (plus1 != 3L) return "Fail 2.1" + if (plus2 != 4L) return "Fail 2.2" + if (plus3 != 5L) return "Fail 2.3" + if (plus4 != 4L) return "Fail 2.4" + if (plus5 != 4L) return "Fail 2.5" + if (plus6 != 4L) return "Fail 2.6" if (plus7 != 4.0f) return "Fail 2.7" if (plus8 != 4.0) return "Fail 2.8" - if (minus1 != -1) return "Fail 3.1" - if (minus2 != 0) return "Fail 3.2" - if (minus3 != 1) return "Fail 3.3" - if (minus4 != 0) return "Fail 3.4" - if (minus5 != 0) return "Fail 3.5" - if (minus6 != 0) return "Fail 3.6" + if (minus1 != -1L) return "Fail 3.1" + if (minus2 != 0L) return "Fail 3.2" + if (minus3 != 1L) return "Fail 3.3" + if (minus4 != 0L) return "Fail 3.4" + if (minus5 != 0L) return "Fail 3.5" + if (minus6 != 0L) return "Fail 3.6" if (minus7 != 0.0f) return "Fail 3.7" if (minus8 != 0.0) return "Fail 3.8" - if (times1 != 2) return "Fail 4.1" - if (times2 != 4) return "Fail 4.2" - if (times3 != 6) return "Fail 4.3" - if (times4 != 4) return "Fail 4.4" - if (times5 != 4) return "Fail 4.5" - if (times6 != 4) return "Fail 4.6" + if (times1 != 2L) return "Fail 4.1" + if (times2 != 4L) return "Fail 4.2" + if (times3 != 6L) return "Fail 4.3" + if (times4 != 4L) return "Fail 4.4" + if (times5 != 4L) return "Fail 4.5" + if (times6 != 4L) return "Fail 4.6" if (times7 != 4.0f) return "Fail 4.7" if (times8 != 4.0) return "Fail 4.8" - if (div1 != 0) return "Fail 5.1" - if (div2 != 1) return "Fail 5.2" - if (div3 != 1) return "Fail 5.3" - if (div4 != 1) return "Fail 5.4" - if (div5 != 1) return "Fail 5.5" - if (div6 != 1) return "Fail 5.6" + if (div1 != 0L) return "Fail 5.1" + if (div2 != 1L) return "Fail 5.2" + if (div3 != 1L) return "Fail 5.3" + if (div4 != 1L) return "Fail 5.4" + if (div5 != 1L) return "Fail 5.5" + if (div6 != 1L) return "Fail 5.6" if (div7 != 1.0f) return "Fail 5.7" if (div8 != 1.0) return "Fail 5.8" - if (rem1 != 1) return "Fail 6.1" - if (rem2 != 0) return "Fail 6.2" - if (rem3 != 1) return "Fail 6.3" - if (rem4 != 0) return "Fail 6.4" - if (rem5 != 0) return "Fail 6.5" - if (rem6 != 0) return "Fail 6.6" + if (rem1 != 1L) return "Fail 6.1" + if (rem2 != 0L) return "Fail 6.2" + if (rem3 != 1L) return "Fail 6.3" + if (rem4 != 0L) return "Fail 6.4" + if (rem5 != 0L) return "Fail 6.5" + if (rem6 != 0L) return "Fail 6.6" if (rem7 != 0.0f) return "Fail 6.7" if (rem8 != 0.0) return "Fail 6.8" - if (unaryPlus1 != 1) return "Fail 7.1" - if (unaryPlus2 != -1) return "Fail 7.2" - if (unaryMinus1 != -1) return "Fail 7.3" - if (unaryMinus2 != 1) return "Fail 7.4" + if (unaryPlus1 != 1L) return "Fail 7.1" + if (unaryPlus2 != -1L) return "Fail 7.2" + if (unaryMinus1 != -1L) return "Fail 7.3" + if (unaryMinus2 != 1L) return "Fail 7.4" - if (convert1 != 1) return "Fail 8.1" + if (convert1 != 1.toByte()) return "Fail 8.1" if (convert2 != '') return "Fail 8.2" - if (convert3 != 1) return "Fail 8.3" + if (convert3 != 1.toShort()) return "Fail 8.3" if (convert4 != 1) return "Fail 8.4" - if (convert5 != 1) return "Fail 8.5" + if (convert5 != 1L) return "Fail 8.5" if (convert6 != 1.0f) return "Fail 8.6" if (convert7 != 1.0) return "Fail 8.7" diff --git a/compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/shortOperations.kt b/compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/shortOperations.kt index 508d401fcb4..d055667a7b4 100644 --- a/compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/shortOperations.kt +++ b/compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/shortOperations.kt @@ -1,7 +1,7 @@ // TARGET_BACKEND: JVM_IR // TARGET_BACKEND: NATIVE // TARGET_BACKEND: JS_IR -// IGNORE_BACKEND_K1: JVM_IR, NATIVE, JS_IR, JS_IR_ES6 +// IGNORE_BACKEND_K1: NATIVE const val minusOneVal = (-1).toShort() const val oneVal = 1.toShort() @@ -106,7 +106,7 @@ fun box(): String { if (plus3 != 5) return "Fail 2.3" if (plus4 != 4) return "Fail 2.4" if (plus5 != 4) return "Fail 2.5" - if (plus6 != 4) return "Fail 2.6" + if (plus6 != 4L) return "Fail 2.6" if (plus7 != 4.0f) return "Fail 2.7" if (plus8 != 4.0) return "Fail 2.8" @@ -115,7 +115,7 @@ fun box(): String { if (minus3 != 1) return "Fail 3.3" if (minus4 != 0) return "Fail 3.4" if (minus5 != 0) return "Fail 3.5" - if (minus6 != 0) return "Fail 3.6" + if (minus6 != 0L) return "Fail 3.6" if (minus7 != 0.0f) return "Fail 3.7" if (minus8 != 0.0) return "Fail 3.8" @@ -124,7 +124,7 @@ fun box(): String { if (times3 != 6) return "Fail 4.3" if (times4 != 4) return "Fail 4.4" if (times5 != 4) return "Fail 4.5" - if (times6 != 4) return "Fail 4.6" + if (times6 != 4L) return "Fail 4.6" if (times7 != 4.0f) return "Fail 4.7" if (times8 != 4.0) return "Fail 4.8" @@ -133,7 +133,7 @@ fun box(): String { if (div3 != 1) return "Fail 5.3" if (div4 != 1) return "Fail 5.4" if (div5 != 1) return "Fail 5.5" - if (div6 != 1) return "Fail 5.6" + if (div6 != 1L) return "Fail 5.6" if (div7 != 1.0f) return "Fail 5.7" if (div8 != 1.0) return "Fail 5.8" @@ -142,7 +142,7 @@ fun box(): String { if (rem3 != 1) return "Fail 6.3" if (rem4 != 0) return "Fail 6.4" if (rem5 != 0) return "Fail 6.5" - if (rem6 != 0) return "Fail 6.6" + if (rem6 != 0L) return "Fail 6.6" if (rem7 != 0.0f) return "Fail 6.7" if (rem8 != 0.0) return "Fail 6.8" @@ -151,11 +151,11 @@ fun box(): String { if (unaryMinus1 != -1) return "Fail 7.3" if (unaryMinus2 != 1) return "Fail 7.4" - if (convert1 != 1) return "Fail 8.1" + if (convert1 != 1.toByte()) return "Fail 8.1" if (convert2 != '') return "Fail 8.2" - if (convert3 != 1) return "Fail 8.3" + if (convert3 != 1.toShort()) return "Fail 8.3" if (convert4 != 1) return "Fail 8.4" - if (convert5 != 1) return "Fail 8.5" + if (convert5 != 1L) return "Fail 8.5" if (convert6 != 1.0f) return "Fail 8.6" if (convert7 != 1.0) return "Fail 8.7" diff --git a/compiler/testData/diagnostics/tests/BinaryCallsOnNullableValues.fir.kt b/compiler/testData/diagnostics/tests/BinaryCallsOnNullableValues.fir.kt index 1fadf2e7bf6..76c71e08a72 100644 --- a/compiler/testData/diagnostics/tests/BinaryCallsOnNullableValues.fir.kt +++ b/compiler/testData/diagnostics/tests/BinaryCallsOnNullableValues.fir.kt @@ -10,16 +10,16 @@ fun f(): Unit { x < 1 x += 1 - x == 1 - x != 1 + x == 1 + x != 1 A() == 1 - x === "1" - x !== "1" + x === "1" + x !== "1" - x === 1 - x !== 1 + x === 1 + x !== 1 x..2 x in 1..2 diff --git a/compiler/testData/diagnostics/tests/IdentityComparisonWithPrimitives.fir.kt b/compiler/testData/diagnostics/tests/IdentityComparisonWithPrimitives.fir.kt index c751e6abca2..74bf1c8fd0b 100644 --- a/compiler/testData/diagnostics/tests/IdentityComparisonWithPrimitives.fir.kt +++ b/compiler/testData/diagnostics/tests/IdentityComparisonWithPrimitives.fir.kt @@ -22,60 +22,60 @@ val a: Any = 0 val na: Any? = 0 // Identity for primitive values of same type -val test_zz = z === z || z !== z -val test_bb = b === b || b !== b -val test_ss = s === s || s !== s -val test_ii = i === i || i !== i -val test_jj = j === j || j !== j -val test_ff = f === f || f !== f -val test_dd = d === d || d !== d -val test_cc = c === c || c !== c +val test_zz = z === z || z !== z +val test_bb = b === b || b !== b +val test_ss = s === s || s !== s +val test_ii = i === i || i !== i +val test_jj = j === j || j !== j +val test_ff = f === f || f !== f +val test_dd = d === d || d !== d +val test_cc = c === c || c !== c // Identity for primitive values of different types (no extra error) -val test_zb = z === b || z !== b +val test_zb = z === b || z !== b // Primitive vs nullable -val test_znz = z === nz || nz === z || z !== nz || nz !== z -val test_bnb = b === nb || nb === b || b !== nb || nb !== b -val test_sns = s === ns || ns === s || s !== ns || ns !== s -val test_ini = i === ni || ni === i || i !== ni || ni !== i -val test_jnj = j === nj || nj === j || j !== nj || nj !== j -val test_fnf = f === nf || nf === f || f !== nf || nf !== f -val test_dnd = d === nd || nd === d || d !== nd || nd !== d -val test_cnc = c === nc || nc === c || c !== nc || nc !== c +val test_znz = z === nz || nz === z || z !== nz || nz !== z +val test_bnb = b === nb || nb === b || b !== nb || nb !== b +val test_sns = s === ns || ns === s || s !== ns || ns !== s +val test_ini = i === ni || ni === i || i !== ni || ni !== i +val test_jnj = j === nj || nj === j || j !== nj || nj !== j +val test_fnf = f === nf || nf === f || f !== nf || nf !== f +val test_dnd = d === nd || nd === d || d !== nd || nd !== d +val test_cnc = c === nc || nc === c || c !== nc || nc !== c // Primitive number vs Number -val test_bn = b === n || n === b || b !== n || n !== b -val test_sn = s === n || n === s || s !== n || n !== s -val test_in = i === n || n === i || i !== n || n !== i -val test_jn = j === n || n === j || j !== n || n !== j -val test_fn = f === n || n === f || f !== n || n !== f -val test_dn = d === n || n === d || d !== n || n !== d +val test_bn = b === n || n === b || b !== n || n !== b +val test_sn = s === n || n === s || s !== n || n !== s +val test_in = i === n || n === i || i !== n || n !== i +val test_jn = j === n || n === j || j !== n || n !== j +val test_fn = f === n || n === f || f !== n || n !== f +val test_dn = d === n || n === d || d !== n || n !== d // Primitive number vs Number? -val test_bnn = b === nn || nn === b || b !== nn || nn !== b -val test_snn = s === nn || nn === s || s !== nn || nn !== s -val test_inn = i === nn || nn === i || i !== nn || nn !== i -val test_jnn = j === nn || nn === j || j !== nn || nn !== j -val test_fnn = f === nn || nn === f || f !== nn || nn !== f -val test_dnn = d === nn || nn === d || d !== nn || nn !== d +val test_bnn = b === nn || nn === b || b !== nn || nn !== b +val test_snn = s === nn || nn === s || s !== nn || nn !== s +val test_inn = i === nn || nn === i || i !== nn || nn !== i +val test_jnn = j === nn || nn === j || j !== nn || nn !== j +val test_fnn = f === nn || nn === f || f !== nn || nn !== f +val test_dnn = d === nn || nn === d || d !== nn || nn !== d // Primitive vs Any -val test_za = z === a || a === z || z !== a || a !== z -val test_ba = b === a || a === b || b !== a || a !== b -val test_sa = s === a || a === s || s !== a || a !== s -val test_ia = i === a || a === i || i !== a || a !== i -val test_ja = j === a || a === j || j !== a || a !== j -val test_fa = f === a || a === f || f !== a || a !== f -val test_da = d === a || a === d || d !== a || a !== d -val test_ca = c === a || a === c || c !== a || a !== c +val test_za = z === a || a === z || z !== a || a !== z +val test_ba = b === a || a === b || b !== a || a !== b +val test_sa = s === a || a === s || s !== a || a !== s +val test_ia = i === a || a === i || i !== a || a !== i +val test_ja = j === a || a === j || j !== a || a !== j +val test_fa = f === a || a === f || f !== a || a !== f +val test_da = d === a || a === d || d !== a || a !== d +val test_ca = c === a || a === c || c !== a || a !== c // Primitive vs Any? -val test_zna = z === na || na === z || z !== na || na !== z -val test_bna = b === na || na === b || b !== na || na !== b -val test_sna = s === na || na === s || s !== na || na !== s -val test_ina = i === na || na === i || i !== na || na !== i -val test_jna = j === na || na === j || j !== na || na !== j -val test_fna = f === na || na === f || f !== na || na !== f -val test_dna = d === na || na === d || d !== na || na !== d -val test_cna = c === na || na === c || c !== na || na !== c \ No newline at end of file +val test_zna = z === na || na === z || z !== na || na !== z +val test_bna = b === na || na === b || b !== na || na !== b +val test_sna = s === na || na === s || s !== na || na !== s +val test_ina = i === na || na === i || i !== na || na !== i +val test_jna = j === na || na === j || j !== na || na !== j +val test_fna = f === na || na === f || f !== na || na !== f +val test_dna = d === na || na === d || d !== na || na !== d +val test_cna = c === na || na === c || c !== na || na !== c diff --git a/compiler/testData/diagnostics/tests/RecursiveTypeParameterEqualityCheck.fir.kt b/compiler/testData/diagnostics/tests/RecursiveTypeParameterEqualityCheck.fir.kt index 92ff5dc9e4c..93fa497b9a6 100644 --- a/compiler/testData/diagnostics/tests/RecursiveTypeParameterEqualityCheck.fir.kt +++ b/compiler/testData/diagnostics/tests/RecursiveTypeParameterEqualityCheck.fir.kt @@ -5,5 +5,5 @@ class Bar3 : Foo fun test(b1: Bar1, b2: Bar2, b3: Bar3) { b1 == b2 - b1 == b3 + b1 == b3 } diff --git a/compiler/testData/diagnostics/tests/comparingArbitraryClasses.fir.kt b/compiler/testData/diagnostics/tests/comparingArbitraryClasses.fir.kt new file mode 100644 index 00000000000..3542584195c --- /dev/null +++ b/compiler/testData/diagnostics/tests/comparingArbitraryClasses.fir.kt @@ -0,0 +1,9 @@ +// ISSUE: KT-29316 +// ISSUE: KT-24284 + +class A +class B +fun main() { + A() == B() + A() === B() +} diff --git a/compiler/testData/diagnostics/tests/comparingArbitraryClasses.kt b/compiler/testData/diagnostics/tests/comparingArbitraryClasses.kt new file mode 100644 index 00000000000..d8dae7edee5 --- /dev/null +++ b/compiler/testData/diagnostics/tests/comparingArbitraryClasses.kt @@ -0,0 +1,9 @@ +// ISSUE: KT-29316 +// ISSUE: KT-24284 + +class A +class B +fun main() { + A() == B() + A() === B() +} diff --git a/compiler/testData/diagnostics/tests/comparingCallableReferencesWithInstanceOfJavaClass.kt b/compiler/testData/diagnostics/tests/comparingCallableReferencesWithInstanceOfJavaClass.kt new file mode 100644 index 00000000000..20615bedb41 --- /dev/null +++ b/compiler/testData/diagnostics/tests/comparingCallableReferencesWithInstanceOfJavaClass.kt @@ -0,0 +1,23 @@ +// FIR_IDENTICAL +// ISSUE: KT-13451 + +// FILE: J.java + +public class J { +} + +// FILE: Main.kt + +class K { + fun f() {} +} + +fun test (j: J, k: K) { + j == K::f + j == k::f + + when (j) { + k::f -> "" + K::f -> "" + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/comparisonOfGenericInterfaceWithGenericClass.kt b/compiler/testData/diagnostics/tests/comparisonOfGenericInterfaceWithGenericClass.kt new file mode 100644 index 00000000000..7261d2be82a --- /dev/null +++ b/compiler/testData/diagnostics/tests/comparisonOfGenericInterfaceWithGenericClass.kt @@ -0,0 +1,7 @@ +// FIR_IDENTICAL +// ISSUE: KT-47884 + +interface A +class B + +fun foo(a: A<*>, b: B<*>): Boolean = a == b diff --git a/compiler/testData/diagnostics/tests/differentNumericTypesFromSmartCast.fir.kt b/compiler/testData/diagnostics/tests/differentNumericTypesFromSmartCast.fir.kt new file mode 100644 index 00000000000..57e3286176d --- /dev/null +++ b/compiler/testData/diagnostics/tests/differentNumericTypesFromSmartCast.fir.kt @@ -0,0 +1,7 @@ +// ISSUE: KT-22499 + +fun test(x: Any, y: Any) = + x is Float && y is Double && x == y + +fun test(x: Float, y: Double) = + x == y diff --git a/compiler/testData/diagnostics/tests/differentNumericTypesFromSmartCast.kt b/compiler/testData/diagnostics/tests/differentNumericTypesFromSmartCast.kt new file mode 100644 index 00000000000..409da498788 --- /dev/null +++ b/compiler/testData/diagnostics/tests/differentNumericTypesFromSmartCast.kt @@ -0,0 +1,7 @@ +// ISSUE: KT-22499 + +fun test(x: Any, y: Any) = + x is Float && y is Double && x == y + +fun test(x: Float, y: Double) = + x == y diff --git a/compiler/testData/diagnostics/tests/enum/compareTwoDifferentEnums.fir.kt b/compiler/testData/diagnostics/tests/enum/compareTwoDifferentEnums.fir.kt deleted file mode 100644 index 5d512b33421..00000000000 --- a/compiler/testData/diagnostics/tests/enum/compareTwoDifferentEnums.fir.kt +++ /dev/null @@ -1,17 +0,0 @@ -// !LANGUAGE: -ProhibitComparisonOfIncompatibleEnums -// FILE: JavaEnumA.java - -public enum JavaEnumA {} - -// FILE: JavaEnumB.java - -public enum JavaEnumB {} - -// FILE: test.kt - -enum class KotlinEnumA -enum class KotlinEnumB - -fun jj(a: JavaEnumA, b: JavaEnumB) = a == b -fun jk(a: JavaEnumA, b: KotlinEnumB) = a == b -fun kk(a: KotlinEnumA, b: KotlinEnumB) = a == b diff --git a/compiler/testData/diagnostics/tests/enum/compareTwoDifferentEnums.kt b/compiler/testData/diagnostics/tests/enum/compareTwoDifferentEnums.kt index b8cb5d9b3a1..049d7c169d2 100644 --- a/compiler/testData/diagnostics/tests/enum/compareTwoDifferentEnums.kt +++ b/compiler/testData/diagnostics/tests/enum/compareTwoDifferentEnums.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !LANGUAGE: -ProhibitComparisonOfIncompatibleEnums // FILE: JavaEnumA.java diff --git a/compiler/testData/diagnostics/tests/enum/equalityOfEnumAndParameter.fir.kt b/compiler/testData/diagnostics/tests/enum/equalityOfEnumAndParameter.fir.kt new file mode 100644 index 00000000000..1760777bf74 --- /dev/null +++ b/compiler/testData/diagnostics/tests/enum/equalityOfEnumAndParameter.fir.kt @@ -0,0 +1,63 @@ +interface Buffered { + fun flush() +} + +interface AIPowered { + fun getAvatarReleaseYear(): Int +} + +enum class BufferedEnum : Buffered { + A, B; + override fun flush() {} +} + +enum class UsualEnum { + C, D; +} + +enum class CleverEnum : Buffered, AIPowered { + E, F; + override fun flush() {} + override fun getAvatarReleaseYear() = 2022 +} + +fun

processInfo1(info: String, printer: P) where P: Buffered, P: AIPowered { + printer == 20 + printer == BufferedEnum.A + printer == UsualEnum.C + printer == CleverEnum.E +} + +fun

processInfo2(info: String, printer: P) where P: AIPowered, P: Buffered { + printer == 20 + printer == BufferedEnum.A + printer == UsualEnum.C + printer == CleverEnum.E +} + +abstract class Printer { + abstract fun print(command: String) +} + +fun

processInfo3(info: String, printer: P) where P: Buffered, P: Printer { + printer == 20 + printer == BufferedEnum.A + printer == UsualEnum.C + printer == CleverEnum.E +} + +fun test(a: Int, b: Any?) { + a === b +} + +fun <T: Int> rest(a: T, b: Any?) where T : String { + a === b +} + +fun <T: Any?> nest(a: Int, b: T) where T : String { + a === b +} + +fun <T: Int, K: Any?> mest(a: T, b: K) where T : String, K: Boolean { + a === b +} diff --git a/compiler/testData/diagnostics/tests/enum/equalityOfEnumAndParameter.kt b/compiler/testData/diagnostics/tests/enum/equalityOfEnumAndParameter.kt new file mode 100644 index 00000000000..c0ac3ad09aa --- /dev/null +++ b/compiler/testData/diagnostics/tests/enum/equalityOfEnumAndParameter.kt @@ -0,0 +1,63 @@ +interface Buffered { + fun flush() +} + +interface AIPowered { + fun getAvatarReleaseYear(): Int +} + +enum class BufferedEnum : Buffered { + A, B; + override fun flush() {} +} + +enum class UsualEnum { + C, D; +} + +enum class CleverEnum : Buffered, AIPowered { + E, F; + override fun flush() {} + override fun getAvatarReleaseYear() = 2022 +} + +fun

processInfo1(info: String, printer: P) where P: Buffered, P: AIPowered { + printer == 20 + printer == BufferedEnum.A + printer == UsualEnum.C + printer == CleverEnum.E +} + +fun

processInfo2(info: String, printer: P) where P: AIPowered, P: Buffered { + printer == 20 + printer == BufferedEnum.A + printer == UsualEnum.C + printer == CleverEnum.E +} + +abstract class Printer { + abstract fun print(command: String) +} + +fun

processInfo3(info: String, printer: P) where P: Buffered, P: Printer { + printer == 20 + printer == BufferedEnum.A + printer == UsualEnum.C + printer == CleverEnum.E +} + +fun test(a: Int, b: Any?) { + a === b +} + +fun <T: Int> rest(a: T, b: Any?) where T : String { + a === b +} + +fun <T: Any?> nest(a: Int, b: T) where T : String { + a === b +} + +fun <T: Int, K: Any?> mest(a: T, b: K) where T : String, K: Boolean { + a === b +} diff --git a/compiler/testData/diagnostics/tests/enum/equalityOfFlexibleTypeParameters.fir.kt b/compiler/testData/diagnostics/tests/enum/equalityOfFlexibleTypeParameters.fir.kt new file mode 100644 index 00000000000..ebf7a979fb0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/enum/equalityOfFlexibleTypeParameters.fir.kt @@ -0,0 +1,13 @@ +// FILE: A.java + +class MyHelpers { + public static T id(T it) { + return it; + } +} + +// FILE: B.kt + +fun <T: Int, K: Any?> mest(a: T, b: K) where T : String, K: Boolean { + MyHelpers.id(a) === MyHelpers.id(b) +} diff --git a/compiler/testData/diagnostics/tests/enum/equalityOfFlexibleTypeParameters.kt b/compiler/testData/diagnostics/tests/enum/equalityOfFlexibleTypeParameters.kt new file mode 100644 index 00000000000..7229444e89c --- /dev/null +++ b/compiler/testData/diagnostics/tests/enum/equalityOfFlexibleTypeParameters.kt @@ -0,0 +1,13 @@ +// FILE: A.java + +class MyHelpers { + public static T id(T it) { + return it; + } +} + +// FILE: B.kt + +fun <T: Int, K: Any?> mest(a: T, b: K) where T : String, K: Boolean { + MyHelpers.id(a) === MyHelpers.id(b) +} diff --git a/compiler/testData/diagnostics/tests/enum/incompatibleEnumEntryClasses.fir.kt b/compiler/testData/diagnostics/tests/enum/incompatibleEnumEntryClasses.fir.kt deleted file mode 100644 index 5fef25a6942..00000000000 --- a/compiler/testData/diagnostics/tests/enum/incompatibleEnumEntryClasses.fir.kt +++ /dev/null @@ -1,92 +0,0 @@ -// !LANGUAGE: -ProhibitComparisonOfIncompatibleEnums - -interface I { - fun foo() -} - -enum class E1 : I { - A { - override fun foo() { - this == E2.A - - val q = this - when (q) { - this -> {} - E1.A -> {} - E1.B -> {} - E2.A -> {} - E2.B -> {} - else -> {} - } - } - }, - B { - override fun foo() { - - } - } -} - -enum class E2 : I { - A { - override fun foo() { - - } - }, - B { - override fun foo() { - - } - } -} - -fun foo1(e1: E1, e2: E2) { - e1 == e2 - e1 != e2 - - e1 == E2.A - E1.B == e2 - - E1.A == E2.B - - e1 == E1.A - E1.A == e1 - e2 == E2.B - E2.B == e2 -} - -fun foo2(e1: E1, e2: E2) { - when (e1) { - E1.A -> {} - E2.A -> {} - E2.B -> {} - e1 -> {} - e2 -> {} - else -> {} - } -} - -fun foo3(e1: Enum, e2: Enum, e: Enum<*>) { - e1 == e - e1 == e2 - - e1 == E1.A - e1 == E2.A - - when (e1) { - e1 -> {} - e2 -> {} - e -> {} - E1.A -> {} - E2.A -> {} - else -> {} - } - - when (e) { - e -> {} - e2 -> {} - E1.A -> {} - E2.A -> {} - else -> {} - } -} diff --git a/compiler/testData/diagnostics/tests/enum/incompatibleEnumEntryClasses.kt b/compiler/testData/diagnostics/tests/enum/incompatibleEnumEntryClasses.kt index d206c690a01..142407b797a 100644 --- a/compiler/testData/diagnostics/tests/enum/incompatibleEnumEntryClasses.kt +++ b/compiler/testData/diagnostics/tests/enum/incompatibleEnumEntryClasses.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !LANGUAGE: -ProhibitComparisonOfIncompatibleEnums interface I { diff --git a/compiler/testData/diagnostics/tests/enum/incompatibleEnums.fir.kt b/compiler/testData/diagnostics/tests/enum/incompatibleEnums.fir.kt index 45498c3a99f..24d1c52d286 100644 --- a/compiler/testData/diagnostics/tests/enum/incompatibleEnums.fir.kt +++ b/compiler/testData/diagnostics/tests/enum/incompatibleEnums.fir.kt @@ -9,13 +9,13 @@ enum class E2 { } fun foo1(e1: E1, e2: E2) { - e1 == e2 - e1 != e2 + e1 == e2 + e1 != e2 - e1 == E2.A - E1.B == e2 + e1 == E2.A + E1.B == e2 - E1.A == E2.B + E1.A == E2.B e1 == E1.A E1.A == e1 @@ -26,27 +26,27 @@ fun foo1(e1: E1, e2: E2) { fun foo2(e1: E1, e2: E2) { when (e1) { E1.A -> {} - E2.A -> {} - E2.B -> {} + E2.A -> {} + E2.B -> {} e1 -> {} - e2 -> {} + e2 -> {} else -> {} } } fun foo3(e1: Enum, e2: Enum, e: Enum<*>) { e1 == e - e1 == e2 + e1 == e2 e1 == E1.A - e1 == E2.A + e1 == E2.A when (e1) { e1 -> {} - e2 -> {} + e2 -> {} e -> {} E1.A -> {} - E2.A -> {} + E2.A -> {} else -> {} } @@ -63,15 +63,15 @@ interface MyInterface open class MyOpenClass fun foo4(e1: E1, i: MyInterface, c: MyOpenClass) { - e1 == i - i == e1 + e1 == i + i == e1 - e1 == c - c == e1 + e1 == c + c == e1 when (e1) { - i -> {} - c -> {} + i -> {} + c -> {} else -> {} } } @@ -90,10 +90,10 @@ fun foo6(e1: E1?, e2: E2) { e1 == null null == e1 - e1 == E2.A - E2.A == e1 - e1 == e2 - e2 == e1 + e1 == E2.A + E2.A == e1 + e1 == e2 + e2 == e1 e2 == null null == e2 @@ -102,7 +102,7 @@ fun foo6(e1: E1?, e2: E2) { } fun foo7(e1: E1?, e2: E2?) { - e1 == e2 // There should be an IDE-inspection for such cases + e1 == e2 // There should be an IDE-inspection for such cases } fun foo8(e1: E1?, e2: E2, t: T) { @@ -117,16 +117,16 @@ fun foo8(e1: E1?, e2: E2, t: T) { } fun foo9(e1: E1?, e2: E2, t: T, k: K) where T : MyInterface, T : MyOpenClass, K : MyInterface { - e1 == t - t == e1 + e1 == t + t == e1 - e2 == t - t == e2 + e2 == t + t == e2 - E1.A == t - t == E1.A + E1.A == t + t == E1.A - E3.X == t + E3.X == t E3.X == k k == E3.X @@ -137,9 +137,9 @@ interface Inv enum class E4 : Inv { A } fun foo10(e4: E4, invString: Inv) { - e4 == invString - invString == e4 + e4 == invString + invString == e4 - E4.A == invString - invString == E4.A + E4.A == invString + invString == E4.A } diff --git a/compiler/testData/diagnostics/tests/enum/incompatibleEnums_1_4.fir.kt b/compiler/testData/diagnostics/tests/enum/incompatibleEnums_1_4.fir.kt index 0062873d753..06387af2b88 100644 --- a/compiler/testData/diagnostics/tests/enum/incompatibleEnums_1_4.fir.kt +++ b/compiler/testData/diagnostics/tests/enum/incompatibleEnums_1_4.fir.kt @@ -26,27 +26,27 @@ fun foo1(e1: E1, e2: E2) { fun foo2(e1: E1, e2: E2) { when (e1) { E1.A -> {} - E2.A -> {} - E2.B -> {} + E2.A -> {} + E2.B -> {} e1 -> {} - e2 -> {} + e2 -> {} else -> {} } } fun foo3(e1: Enum, e2: Enum, e: Enum<*>) { e1 == e - e1 == e2 + e1 == e2 e1 == E1.A - e1 == E2.A + e1 == E2.A when (e1) { e1 -> {} - e2 -> {} + e2 -> {} e -> {} E1.A -> {} - E2.A -> {} + E2.A -> {} else -> {} } @@ -70,8 +70,8 @@ fun foo4(e1: E1, i: MyInterface, c: MyOpenClass) { c == e1 when (e1) { - i -> {} - c -> {} + i -> {} + c -> {} else -> {} } } @@ -102,7 +102,7 @@ fun foo6(e1: E1?, e2: E2) { } fun foo7(e1: E1?, e2: E2?) { - e1 == e2 // There should be an IDE-inspection for such cases + e1 == e2 // There should be an IDE-inspection for such cases } fun foo8(e1: E1?, e2: E2, t: T) { @@ -117,16 +117,16 @@ fun foo8(e1: E1?, e2: E2, t: T) { } fun foo9(e1: E1?, e2: E2, t: T, k: K) where T : MyInterface, T : MyOpenClass, K : MyInterface { - e1 == t - t == e1 + e1 == t + t == e1 - e2 == t - t == e2 + e2 == t + t == e2 - E1.A == t - t == E1.A + E1.A == t + t == E1.A - E3.X == t + E3.X == t E3.X == k k == E3.X @@ -137,9 +137,9 @@ interface Inv enum class E4 : Inv { A } fun foo10(e4: E4, invString: Inv) { - e4 == invString - invString == e4 + e4 == invString + invString == e4 - E4.A == invString - invString == E4.A + E4.A == invString + invString == E4.A } diff --git a/compiler/testData/diagnostics/tests/enum/typeCompatibility.fir.kt b/compiler/testData/diagnostics/tests/enum/typeCompatibility.fir.kt index dc682e1ca99..d635b4d1cce 100644 --- a/compiler/testData/diagnostics/tests/enum/typeCompatibility.fir.kt +++ b/compiler/testData/diagnostics/tests/enum/typeCompatibility.fir.kt @@ -56,47 +56,47 @@ fun foo( "" == 2 string == int - strings == ints + strings == ints - aString == aInt - aOutString == aOutInt + aString == aInt + aOutString == aOutInt aInString == aInInt - aOutString == aInInt - aInString == aOutInt - aOutString == aInt - aInString == aInt - aOutString2 == aOutInt2 + aOutString == aInInt + aInString == aOutInt + aOutString == aInt + aInString == aInt + aOutString2 == aOutInt2 aInString2 == aInInt2 - aOutString2 == aInInt2 - aInString2 == aOutInt2 - aString == a2 + aOutString2 == aInInt2 + aInString2 == aOutInt2 + aString == a2 - bString == bInt - bOutString == bOutInt + bString == bInt + bOutString == bOutInt bInString == bInInt - bOutString == bInInt - bInString == bOutInt - bOutString == bInt - bInString == bInt - bOutString2 == bOutInt2 + bOutString == bInInt + bInString == bOutInt + bOutString == bInt + bInString == bInt + bOutString2 == bOutInt2 bInString2 == bInInt2 - bOutString2 == bInInt2 - bInString2 == bOutInt2 + bOutString2 == bInInt2 + bInString2 == bOutInt2 e == i "" == i - ac == ad + ac == ad - tSub1 == tSub2 + tSub1 == tSub2 - aString == bString + aString == bString - aListInt == aSetInt - aSetInt == aListString - aListString == aListInt + aListInt == aSetInt + aSetInt == aListString + aListString == aListInt - aString == aListString - bString == aListString + aString == aListString + bString == aListString - mutableListAny == listString + mutableListAny == listString } diff --git a/compiler/testData/diagnostics/tests/equalityComparisonToSelf.kt b/compiler/testData/diagnostics/tests/equalityComparisonToSelf.kt new file mode 100644 index 00000000000..040813cb64f --- /dev/null +++ b/compiler/testData/diagnostics/tests/equalityComparisonToSelf.kt @@ -0,0 +1,7 @@ +// FIR_IDENTICAL +// ISSUE: KTIJ-15380 + +fun test() { + var x = 0 + if (x == x) {} +} diff --git a/compiler/testData/diagnostics/tests/equalityWithSmartCastInIfBlock.fir.kt b/compiler/testData/diagnostics/tests/equalityWithSmartCastInIfBlock.fir.kt new file mode 100644 index 00000000000..6072c927754 --- /dev/null +++ b/compiler/testData/diagnostics/tests/equalityWithSmartCastInIfBlock.fir.kt @@ -0,0 +1,8 @@ +// ISSUE: KT-46383 + +fun test(a: Any, b: Any, s: String, i: Int) { + if (a is String && b is Int) { + a == b + } + s == i +} diff --git a/compiler/testData/diagnostics/tests/equalityWithSmartCastInIfBlock.kt b/compiler/testData/diagnostics/tests/equalityWithSmartCastInIfBlock.kt new file mode 100644 index 00000000000..63388872c5d --- /dev/null +++ b/compiler/testData/diagnostics/tests/equalityWithSmartCastInIfBlock.kt @@ -0,0 +1,8 @@ +// ISSUE: KT-46383 + +fun test(a: Any, b: Any, s: String, i: Int) { + if (a is String && b is Int) { + a == b + } + s == i +} diff --git a/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypes.fir.kt b/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypes.fir.kt index 168abd6f8af..5973062d33d 100644 --- a/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypes.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypes.fir.kt @@ -3,18 +3,18 @@ fun main(x: Long, y: Int) { sequence { - 1L == 3 - x == 3 - 3 == 1L - 3 == x - y == x + 1L == 3 + x == 3 + 3 == 1L + 3 == x + y == x - 1L === 3 - x === 3 - 3 === 1L - 3 === x - y === x + 1L === 3 + x === 3 + 3 === 1L + 3 === x + y === x yield("") } -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypesProgressive.fir.kt b/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypesProgressive.fir.kt index 2f8ed407c2e..d2b1ecdb4ea 100644 --- a/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypesProgressive.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypesProgressive.fir.kt @@ -3,18 +3,18 @@ fun main(x: Long, y: Int) { sequence { - 1L == 3 - x == 3 - 3 == 1L - 3 == x - y == x + 1L == 3 + x == 3 + 3 == 1L + 3 == x + y == x - 1L === 3 - x === 3 - 3 === 1L - 3 === x - y === x + 1L === 3 + x === 3 + 3 === 1L + 3 === x + y === x yield("") } -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/inlineClasses/identityComparisonWithInlineClasses.fir.kt b/compiler/testData/diagnostics/tests/inlineClasses/identityComparisonWithInlineClasses.fir.kt index bcb23a88bc6..09fdf8a41ba 100644 --- a/compiler/testData/diagnostics/tests/inlineClasses/identityComparisonWithInlineClasses.fir.kt +++ b/compiler/testData/diagnostics/tests/inlineClasses/identityComparisonWithInlineClasses.fir.kt @@ -5,18 +5,18 @@ inline class Foo(val x: Int) inline class Bar(val y: String) fun test(f1: Foo, f2: Foo, b1: Bar, fn1: Foo?, fn2: Foo?) { - val a1 = f1 === f2 || f1 !== f2 - val a2 = f1 === f1 - val a3 = f1 === b1 || f1 !== b1 + val a1 = f1 === f2 || f1 !== f2 + val a2 = f1 === f1 + val a3 = f1 === b1 || f1 !== b1 val c1 = fn1 === fn2 || fn1 !== fn2 - val c2 = f1 === fn1 || f1 !== fn1 - val c3 = b1 === fn1 || b1 !== fn1 + val c2 = f1 === fn1 || f1 !== fn1 + val c3 = b1 === fn1 || b1 !== fn1 val any = Any() - val d1 = any === f1 || any !== f1 - val d2 = f1 === any || f1 !== any + val d1 = any === f1 || any !== f1 + val d2 = f1 === any || f1 !== any val d3 = any === fn1 || any !== fn1 val d4 = fn1 === any || fn1 !== any } diff --git a/compiler/testData/diagnostics/tests/modifiers/const/equals_after.fir.kt b/compiler/testData/diagnostics/tests/modifiers/const/equals_after.fir.kt index b4ae0448970..cd60c7ac823 100644 --- a/compiler/testData/diagnostics/tests/modifiers/const/equals_after.fir.kt +++ b/compiler/testData/diagnostics/tests/modifiers/const/equals_after.fir.kt @@ -3,12 +3,12 @@ const val equalsBoolean1 = true.equals(true) const val equalsBoolean2 = false != true const val equalsBoolean3 = false.equals(1) -const val equalsBoolean4 = false == 1 +const val equalsBoolean4 = false == 1 const val equalsChar1 = '1'.equals('2') const val equalsChar2 = '2' == '2' const val equalsChar3 = '1'.equals(1) -const val equalsChar4 = '1' == 1 +const val equalsChar4 = '1' == 1 const val equalsByte1 = 1.toByte().equals(2.toByte()) const val equalsByte2 = 2.toByte() == 2.toByte() diff --git a/compiler/testData/diagnostics/tests/modifiers/const/equals_before.fir.kt b/compiler/testData/diagnostics/tests/modifiers/const/equals_before.fir.kt index 2d43fc2ed93..b4da50686ba 100644 --- a/compiler/testData/diagnostics/tests/modifiers/const/equals_before.fir.kt +++ b/compiler/testData/diagnostics/tests/modifiers/const/equals_before.fir.kt @@ -3,12 +3,12 @@ const val equalsBoolean1 = true.equals(true) const val equalsBoolean2 = false != true const val equalsBoolean3 = false.equals(1) -const val equalsBoolean4 = false == 1 +const val equalsBoolean4 = false == 1 const val equalsChar1 = '1'.equals('2') const val equalsChar2 = '2' == '2' const val equalsChar3 = '1'.equals(1) -const val equalsChar4 = '1' == 1 +const val equalsChar4 = '1' == 1 const val equalsByte1 = 1.toByte().equals(2.toByte()) const val equalsByte2 = 2.toByte() == 2.toByte() diff --git a/compiler/testData/diagnostics/tests/nullabilityAndSmartCasts/kt1778.fir.kt b/compiler/testData/diagnostics/tests/nullabilityAndSmartCasts/kt1778.fir.kt index b85a1fe3067..ad92ea64684 100644 --- a/compiler/testData/diagnostics/tests/nullabilityAndSmartCasts/kt1778.fir.kt +++ b/compiler/testData/diagnostics/tests/nullabilityAndSmartCasts/kt1778.fir.kt @@ -8,8 +8,8 @@ import checkSubtype fun main(args : Array) { val x = checkSubtype(args[0]) if(x is java.lang.CharSequence) { - if ("a" == x) x.length else x.length() // OK - if ("a" == x || "b" == x) x.length else x.length() // <– THEN ERROR - if ("a" == x && "a" == x) x.length else x.length() // <– ELSE ERROR + if ("a" == x) x.length else x.length() // OK + if ("a" == x || "b" == x) x.length else x.length() // <– THEN ERROR + if ("a" == x && "a" == x) x.length else x.length() // <– ELSE ERROR } } diff --git a/compiler/testData/diagnostics/tests/sealed/TreeWhenFunctionalNoIs.fir.kt b/compiler/testData/diagnostics/tests/sealed/TreeWhenFunctionalNoIs.fir.kt index dbe0f0cdf10..3e2555f93fd 100644 --- a/compiler/testData/diagnostics/tests/sealed/TreeWhenFunctionalNoIs.fir.kt +++ b/compiler/testData/diagnostics/tests/sealed/TreeWhenFunctionalNoIs.fir.kt @@ -11,7 +11,7 @@ sealed class Tree { fun maxIsClass(): Int = when(this) { Empty -> -1 - Leaf -> 0 + Leaf -> 0 is Node -> this.left.max() } diff --git a/compiler/testData/diagnostics/tests/unsignedTypes/forbiddenEqualsOnUnsignedTypes.fir.kt b/compiler/testData/diagnostics/tests/unsignedTypes/forbiddenEqualsOnUnsignedTypes.fir.kt index 67380a436ea..284a948765e 100644 --- a/compiler/testData/diagnostics/tests/unsignedTypes/forbiddenEqualsOnUnsignedTypes.fir.kt +++ b/compiler/testData/diagnostics/tests/unsignedTypes/forbiddenEqualsOnUnsignedTypes.fir.kt @@ -6,18 +6,18 @@ fun test( ui1: UInt, ui2: UInt, ul1: ULong, ul2: ULong ) { - val ub = ub1 === ub2 || ub1 !== ub2 - val us = us1 === us2 || us1 !== us2 - val ui = ui1 === ui2 || ui1 !== ui2 - val ul = ul1 === ul2 || ul1 !== ul2 + val ub = ub1 === ub2 || ub1 !== ub2 + val us = us1 === us2 || us1 !== us2 + val ui = ui1 === ui2 || ui1 !== ui2 + val ul = ul1 === ul2 || ul1 !== ul2 - val u = ub1 === ul1 + val u = ub1 === ul1 - val a1 = 1u === 2u || 1u !== 2u - val a2 = 0xFFFF_FFFF_FFFF_FFFFu === 0xFFFF_FFFF_FFFF_FFFFu + val a1 = 1u === 2u || 1u !== 2u + val a2 = 0xFFFF_FFFF_FFFF_FFFFu === 0xFFFF_FFFF_FFFF_FFFFu val bu1 = 1u val bu2 = 1u - val c1 = bu1 === bu2 || bu1 !== bu2 + val c1 = bu1 === bu2 || bu1 !== bu2 } diff --git a/compiler/testData/diagnostics/tests/valueClasses/identityComparisonWithValueClasses.fir.kt b/compiler/testData/diagnostics/tests/valueClasses/identityComparisonWithValueClasses.fir.kt index 11eff5fa286..dafcbba02e3 100644 --- a/compiler/testData/diagnostics/tests/valueClasses/identityComparisonWithValueClasses.fir.kt +++ b/compiler/testData/diagnostics/tests/valueClasses/identityComparisonWithValueClasses.fir.kt @@ -13,18 +13,18 @@ value class Foo(val x: Int) value class Bar(val y: String) fun test(f1: Foo, f2: Foo, b1: Bar, fn1: Foo?, fn2: Foo?) { - val a1 = f1 === f2 || f1 !== f2 - val a2 = f1 === f1 - val a3 = f1 === b1 || f1 !== b1 + val a1 = f1 === f2 || f1 !== f2 + val a2 = f1 === f1 + val a3 = f1 === b1 || f1 !== b1 val c1 = fn1 === fn2 || fn1 !== fn2 - val c2 = f1 === fn1 || f1 !== fn1 - val c3 = b1 === fn1 || b1 !== fn1 + val c2 = f1 === fn1 || f1 !== fn1 + val c3 = b1 === fn1 || b1 !== fn1 val any = Any() - val d1 = any === f1 || any !== f1 - val d2 = f1 === any || f1 !== any + val d1 = any === f1 || any !== f1 + val d2 = f1 === any || f1 !== any val d3 = any === fn1 || any !== fn1 val d4 = fn1 === any || fn1 !== any } diff --git a/compiler/testData/diagnostics/tests/when/When.fir.kt b/compiler/testData/diagnostics/tests/when/When.fir.kt index 424056e94cd..d9b6955b9bb 100644 --- a/compiler/testData/diagnostics/tests/when/When.fir.kt +++ b/compiler/testData/diagnostics/tests/when/When.fir.kt @@ -22,7 +22,7 @@ fun foo() : Int { !is Int -> 1 is Any? -> 1 is Any -> 1 - s -> 1 + s -> 1 1 -> 1 1 + a -> 1 in 1..a -> 1 diff --git a/compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditionsNoSubject.fir.kt b/compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditionsNoSubject.fir.kt index 3218bfac558..ebec5dd553d 100644 --- a/compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditionsNoSubject.fir.kt +++ b/compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditionsNoSubject.fir.kt @@ -47,8 +47,8 @@ fun testWithSubject_ok(x: Boolean, y: Boolean?, any: Any, z: Boolean) { x >= x -> {} x == x -> {} x != x -> {} - x === x -> {} - x !== x -> {} + x === x -> {} + x !== x -> {} x && x -> {} x || x -> {} } diff --git a/compiler/testData/diagnostics/testsWithStdLib/comparingDifferentSubclassesCommonInterface.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/comparingDifferentSubclassesCommonInterface.fir.kt new file mode 100644 index 00000000000..77ad8ad0502 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/comparingDifferentSubclassesCommonInterface.fir.kt @@ -0,0 +1,10 @@ +// ISSUE: KT-54473 + +interface I +class A : I +class B : I + +fun test(a: A, b: B) { + a == b + a == b as I +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/comparingDifferentSubclassesCommonInterface.kt b/compiler/testData/diagnostics/testsWithStdLib/comparingDifferentSubclassesCommonInterface.kt new file mode 100644 index 00000000000..abcba613970 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/comparingDifferentSubclassesCommonInterface.kt @@ -0,0 +1,10 @@ +// ISSUE: KT-54473 + +interface I +class A : I +class B : I + +fun test(a: A, b: B) { + a == b + a == b as I +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/comparingPlatformTypes.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/comparingPlatformTypes.fir.kt new file mode 100644 index 00000000000..2baf7b005e2 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/comparingPlatformTypes.fir.kt @@ -0,0 +1,14 @@ +// ISSUE: KT-25808 +// WITH_STDLIB + +// B.java +public class B { +} + +// test.kt +class A + +fun main(args: Array) { + (1 to A()) == A() + (1 to B()) == B() +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/comparingPlatformTypes.kt b/compiler/testData/diagnostics/testsWithStdLib/comparingPlatformTypes.kt new file mode 100644 index 00000000000..f8fb90e7df7 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/comparingPlatformTypes.kt @@ -0,0 +1,14 @@ +// ISSUE: KT-25808 +// WITH_STDLIB + +// B.java +public class B { +} + +// test.kt +class A + +fun main(args: Array) { + (1 to A()) == A() + (1 to B()) == B() +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/comparingSmartCastValueToBoolean.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/comparingSmartCastValueToBoolean.fir.kt new file mode 100644 index 00000000000..626a2dee319 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/comparingSmartCastValueToBoolean.fir.kt @@ -0,0 +1,23 @@ +// ISSUE: KT-35134 + +interface A + +fun foo(a: Any) { + if (a is A) { + if (a == (a == 1)) { + println(1) + } + + when (a) { + a == 1 -> print("1") + } + + if ((a as A) == (a == 1)) { + println(1) + } + + when (a as A) { + a == 1 -> print("1") + } + } +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/comparingSmartCastValueToBoolean.kt b/compiler/testData/diagnostics/testsWithStdLib/comparingSmartCastValueToBoolean.kt new file mode 100644 index 00000000000..3662b4ea8fd --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/comparingSmartCastValueToBoolean.kt @@ -0,0 +1,23 @@ +// ISSUE: KT-35134 + +interface A + +fun foo(a: Any) { + if (a is A) { + if (a == (a == 1)) { + println(1) + } + + when (a) { + a == 1 -> print("1") + } + + if ((a as A) == (a == 1)) { + println(1) + } + + when (a as A) { + a == 1 -> print("1") + } + } +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/comparingTripleWithPair.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/comparingTripleWithPair.fir.kt new file mode 100644 index 00000000000..2ef82db994e --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/comparingTripleWithPair.fir.kt @@ -0,0 +1,10 @@ +// ISSUE: KT-47979 + +enum class Foo { A, B } + +fun test() { + if (Triple(Foo.A, 1, 2) == Pair("a", "b")) println("Doesn't compile") + if (Triple(0, 1, 2) == Pair(Foo.A, "a")) println("Doesn't compile") + if (Triple(0, 1, 2) == Pair("a", "b")) println("Doesn't compile") + if (Triple(Foo.A, 1, 2) == Pair(Foo.A, "a")) println("Compiles, but why?") +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/comparingTripleWithPair.kt b/compiler/testData/diagnostics/testsWithStdLib/comparingTripleWithPair.kt new file mode 100644 index 00000000000..cfb6b7cb36e --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/comparingTripleWithPair.kt @@ -0,0 +1,10 @@ +// ISSUE: KT-47979 + +enum class Foo { A, B } + +fun test() { + if (Triple(Foo.A, 1, 2) == Pair("a", "b")) println("Doesn't compile") + if (Triple(0, 1, 2) == Pair(Foo.A, "a")) println("Doesn't compile") + if (Triple(0, 1, 2) == Pair("a", "b")) println("Doesn't compile") + if (Triple(Foo.A, 1, 2) == Pair(Foo.A, "a")) println("Compiles, but why?") +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityCommonCases.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityCommonCases.fir.kt new file mode 100644 index 00000000000..dfa99aefcaf --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityCommonCases.fir.kt @@ -0,0 +1,74 @@ +interface B + +fun equalityNotApplicable(a: Int, b: B) { + a == b +} + +fun equalityNotApplicableSmartCast(a: Any?, b: Any?) { + if (a is Int && b is B) { + a == b + } +} + +@JvmInline +value class C(val int: Int) +@JvmInline +value class D(val bool: Boolean) + +fun forbiddenIdentityEquals(c: C, d: D) { + c === d +} + +fun forbiddenIdentityEqualsSmartCast(c: Any?, d: Any?) { + if (c is C && d is D) { + c === d + } +} + +fun implicitBoxingInIdentityEquals(i: Int, a: Any?) { + i === a +} + +fun implicitBoxingInIdentityEqualsSmartCast(i: Any?, a: Any?) { + if (i is Int) { + i === a + } +} + +fun deprecatedIdentityEquals(a: Int, b: Int) { + a === b +} + +fun deprecatedIdentityEqualsSmartCast(a: Any?, b: Any?) { + if (a is Int && b is Int) { + a === b + } +} + +fun incompatibleTypes(a: Int) = when(a) { + C(10) -> 1 + else -> 2 +} + +fun incompatibleTypesSmartCast(a: Any?) { + if (a is Int) { + when(a) { + C(10) -> 1 + else -> 2 + } + } +} + +enum class E { + A, B +} + +fun incompatibleEnumComparison(c: B, e: E) { + c == e +} + +fun incompatibleEnumComparisonSmartCast(c: Any?, e: Any?) { + if (c is B && e is E) { + c == e + } +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityCommonCases.kt b/compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityCommonCases.kt new file mode 100644 index 00000000000..563ceff1f78 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityCommonCases.kt @@ -0,0 +1,74 @@ +interface B + +fun equalityNotApplicable(a: Int, b: B) { + a == b +} + +fun equalityNotApplicableSmartCast(a: Any?, b: Any?) { + if (a is Int && b is B) { + a == b + } +} + +@JvmInline +value class C(val int: Int) +@JvmInline +value class D(val bool: Boolean) + +fun forbiddenIdentityEquals(c: C, d: D) { + c === d +} + +fun forbiddenIdentityEqualsSmartCast(c: Any?, d: Any?) { + if (c is C && d is D) { + c === d + } +} + +fun implicitBoxingInIdentityEquals(i: Int, a: Any?) { + i === a +} + +fun implicitBoxingInIdentityEqualsSmartCast(i: Any?, a: Any?) { + if (i is Int) { + i === a + } +} + +fun deprecatedIdentityEquals(a: Int, b: Int) { + a === b +} + +fun deprecatedIdentityEqualsSmartCast(a: Any?, b: Any?) { + if (a is Int && b is Int) { + a === b + } +} + +fun incompatibleTypes(a: Int) = when(a) { + C(10) -> 1 + else -> 2 +} + +fun incompatibleTypesSmartCast(a: Any?) { + if (a is Int) { + when(a) { + C(10) -> 1 + else -> 2 + } + } +} + +enum class E { + A, B +} + +fun incompatibleEnumComparison(c: B, e: E) { + c == e +} + +fun incompatibleEnumComparisonSmartCast(c: Any?, e: Any?) { + if (c is B && e is E) { + c == e + } +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_Off.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_Off.fir.kt new file mode 100644 index 00000000000..2f7bf5a91c5 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_Off.fir.kt @@ -0,0 +1,38 @@ +// LANGUAGE: +ReportErrorsForComparisonOperators + +fun nullableNothingIdentity(a: Int, b: Nothing?) { + a === b +} + +fun samePrimitiveIdentity(a: Int, b: Int) { + a === b +} + +fun identityWithImplicitBoxing(a: Int, b: Any?) { + a === b +} + +enum class E1 { A, B } +enum class E2 { C, D } + +fun nullableEnums(a: E1?, b: E2?) { + a == b +} + +fun enumAsTypeParameterBound(a: T, b: Int) where T : Any, T : E1 { + a == b +} + +fun twoTypeParameters(a: T, b: K) where T : Number, K : String { + a == b +} + +interface I1 +interface I2 + +enum class E3 : I1 { A, B } + +fun compareTypeParameterWithEnum(a: A) where A: I1, A: I2 { + a == E1.A + a == E3.A +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_Off.kt b/compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_Off.kt new file mode 100644 index 00000000000..ab923ebe702 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_Off.kt @@ -0,0 +1,38 @@ +// LANGUAGE: +ReportErrorsForComparisonOperators + +fun nullableNothingIdentity(a: Int, b: Nothing?) { + a === b +} + +fun samePrimitiveIdentity(a: Int, b: Int) { + a === b +} + +fun identityWithImplicitBoxing(a: Int, b: Any?) { + a === b +} + +enum class E1 { A, B } +enum class E2 { C, D } + +fun nullableEnums(a: E1?, b: E2?) { + a == b +} + +fun enumAsTypeParameterBound(a: T, b: Int) where T : Any, T : E1 { + a == b +} + +fun twoTypeParameters(a: T, b: K) where T : Number, K : String { + a == b +} + +interface I1 +interface I2 + +enum class E3 : I1 { A, B } + +fun compareTypeParameterWithEnum(a: A) where A: I1, A: I2 { + a == E1.A + a == E3.A +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_On.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_On.fir.kt new file mode 100644 index 00000000000..753d62dca33 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_On.fir.kt @@ -0,0 +1,38 @@ +// LANGUAGE: -ReportErrorsForComparisonOperators + +fun nullableNothingIdentity(a: Int, b: Nothing?) { + a === b +} + +fun samePrimitiveIdentity(a: Int, b: Int) { + a === b +} + +fun identityWithImplicitBoxing(a: Int, b: Any?) { + a === b +} + +enum class E1 { A, B } +enum class E2 { C, D } + +fun nullableEnums(a: E1?, b: E2?) { + a == b +} + +fun enumAsTypeParameterBound(a: T, b: Int) where T : Any, T : E1 { + a == b +} + +fun twoTypeParameters(a: T, b: K) where T : Number, K : String { + a == b +} + +interface I1 +interface I2 + +enum class E3 : I1 { A, B } + +fun compareTypeParameterWithEnum(a: A) where A: I1, A: I2 { + a == E1.A + a == E3.A +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_On.kt b/compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_On.kt new file mode 100644 index 00000000000..3190ff6c6f6 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_On.kt @@ -0,0 +1,38 @@ +// LANGUAGE: -ReportErrorsForComparisonOperators + +fun nullableNothingIdentity(a: Int, b: Nothing?) { + a === b +} + +fun samePrimitiveIdentity(a: Int, b: Int) { + a === b +} + +fun identityWithImplicitBoxing(a: Int, b: Any?) { + a === b +} + +enum class E1 { A, B } +enum class E2 { C, D } + +fun nullableEnums(a: E1?, b: E2?) { + a == b +} + +fun enumAsTypeParameterBound(a: T, b: Int) where T : Any, T : E1 { + a == b +} + +fun twoTypeParameters(a: T, b: K) where T : Number, K : String { + a == b +} + +interface I1 +interface I2 + +enum class E3 : I1 { A, B } + +fun compareTypeParameterWithEnum(a: A) where A: I1, A: I2 { + a == E1.A + a == E3.A +} 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 c2eb06681af..67954b46905 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 @@ -159,6 +159,24 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/CompareToWithErrorType.kt"); } + @Test + @TestMetadata("comparingArbitraryClasses.kt") + public void testComparingArbitraryClasses() throws Exception { + runTest("compiler/testData/diagnostics/tests/comparingArbitraryClasses.kt"); + } + + @Test + @TestMetadata("comparingCallableReferencesWithInstanceOfJavaClass.kt") + public void testComparingCallableReferencesWithInstanceOfJavaClass() throws Exception { + runTest("compiler/testData/diagnostics/tests/comparingCallableReferencesWithInstanceOfJavaClass.kt"); + } + + @Test + @TestMetadata("comparisonOfGenericInterfaceWithGenericClass.kt") + public void testComparisonOfGenericInterfaceWithGenericClass() throws Exception { + runTest("compiler/testData/diagnostics/tests/comparisonOfGenericInterfaceWithGenericClass.kt"); + } + @Test @TestMetadata("Constants.kt") public void testConstants() throws Exception { @@ -243,6 +261,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/DiamondProperty.kt"); } + @Test + @TestMetadata("differentNumericTypesFromSmartCast.kt") + public void testDifferentNumericTypesFromSmartCast() throws Exception { + runTest("compiler/testData/diagnostics/tests/differentNumericTypesFromSmartCast.kt"); + } + @Test @TestMetadata("Dollar.kt") public void testDollar() throws Exception { @@ -255,6 +279,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/EnumEntryAsType.kt"); } + @Test + @TestMetadata("equalityComparisonToSelf.kt") + public void testEqualityComparisonToSelf() throws Exception { + runTest("compiler/testData/diagnostics/tests/equalityComparisonToSelf.kt"); + } + + @Test + @TestMetadata("equalityWithSmartCastInIfBlock.kt") + public void testEqualityWithSmartCastInIfBlock() throws Exception { + runTest("compiler/testData/diagnostics/tests/equalityWithSmartCastInIfBlock.kt"); + } + @Test @TestMetadata("ExtensionCallInvoke.kt") public void testExtensionCallInvoke() throws Exception { @@ -10398,6 +10434,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/enum/enumWithEmptyName.kt"); } + @Test + @TestMetadata("equalityOfEnumAndParameter.kt") + public void testEqualityOfEnumAndParameter() throws Exception { + runTest("compiler/testData/diagnostics/tests/enum/equalityOfEnumAndParameter.kt"); + } + + @Test + @TestMetadata("equalityOfFlexibleTypeParameters.kt") + public void testEqualityOfFlexibleTypeParameters() throws Exception { + runTest("compiler/testData/diagnostics/tests/enum/equalityOfFlexibleTypeParameters.kt"); + } + @Test @TestMetadata("ExplicitConstructorCall.kt") public void testExplicitConstructorCall() throws Exception { @@ -36203,6 +36251,30 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/testsWithStdLib/commonCollections.kt"); } + @Test + @TestMetadata("comparingDifferentSubclassesCommonInterface.kt") + public void testComparingDifferentSubclassesCommonInterface() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/comparingDifferentSubclassesCommonInterface.kt"); + } + + @Test + @TestMetadata("comparingPlatformTypes.kt") + public void testComparingPlatformTypes() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/comparingPlatformTypes.kt"); + } + + @Test + @TestMetadata("comparingSmartCastValueToBoolean.kt") + public void testComparingSmartCastValueToBoolean() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/comparingSmartCastValueToBoolean.kt"); + } + + @Test + @TestMetadata("comparingTripleWithPair.kt") + public void testComparingTripleWithPair() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/comparingTripleWithPair.kt"); + } + @Test @TestMetadata("compileTimeUnsignedArray.kt") public void testCompileTimeUnsignedArray() throws Exception { @@ -36227,6 +36299,24 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/testsWithStdLib/enumEntryInitialization.kt"); } + @Test + @TestMetadata("equalityCompatibilityCommonCases.kt") + public void testEqualityCompatibilityCommonCases() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityCommonCases.kt"); + } + + @Test + @TestMetadata("equalityCompatibilityOldBehavior_Off.kt") + public void testEqualityCompatibilityOldBehavior_Off() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_Off.kt"); + } + + @Test + @TestMetadata("equalityCompatibilityOldBehavior_On.kt") + public void testEqualityCompatibilityOldBehavior_On() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_On.kt"); + } + @Test @TestMetadata("exitProcess.kt") public void testExitProcess() throws Exception { diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/1.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/1.fir.kt index defa50e5648..077d0e19d02 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/1.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/1.fir.kt @@ -21,7 +21,7 @@ fun case_1(x: Any?) { // TESTCASE NUMBER: 3 fun case_3() { - if (Object.prop_1 == null !== null) + if (Object.prop_1 == null !== null) else { Object.prop_1 Object.prop_1.equals(null) @@ -56,7 +56,7 @@ fun case_4(x: Char?) { fun case_5() { val x: Unit? = null - if (x !== null is Boolean?) x + if (x !== null is Boolean?) x if (x !== null == null) x.equals(null) if (x !== null == null) x.propT if (x !== null == null) x.propAny @@ -88,7 +88,7 @@ fun case_6(x: EmptyClass?) { // TESTCASE NUMBER: 7 fun case_7() { - if (nullableNumberProperty != null || nullableNumberProperty != null is Boolean) { + if (nullableNumberProperty != null || nullableNumberProperty != null is Boolean) { nullableNumberProperty nullableNumberProperty.equals(null) nullableNumberProperty.propT @@ -104,13 +104,13 @@ fun case_7() { // TESTCASE NUMBER: 8 fun case_8(x: TypealiasNullableString) { - if (x !== null === null && x != null != null) x.get(0) - if (x !== null != null && x != null === null) x.get(0) + if (x !== null === null && x != null != null) x.get(0) + if (x !== null != null && x != null === null) x.get(0) } // TESTCASE NUMBER: 9 fun case_9(x: TypealiasNullableString?) { - if (x === null === null) { + if (x === null === null) { } else if (false is Boolean) { x @@ -123,7 +123,7 @@ fun case_10() { val a = Class() if (a.prop_4 === null || true is Boolean) { - if (a.prop_4 != null !== null) { + if (a.prop_4 != null !== null) { a.prop_4 a.prop_4.equals(null) a.prop_4.propT @@ -166,8 +166,8 @@ fun case_11(x: TypealiasNullableStringIndirect?, y: Typ // TESTCASE NUMBER: 12 fun case_12(x: TypealiasNullableStringIndirect, y: TypealiasNullableStringIndirect) = - if ((x == null) !is Boolean === false) "1" - else if ((y === null !== null) is Boolean) x + if ((x == null) !is Boolean === false) "1" + else if ((y === null !== null) is Boolean) x else if (y === null != null) x.equals(null) else if (y === null != null) x.propT else if (y === null != null) x.propAny @@ -181,7 +181,7 @@ fun case_12(x: TypealiasNullableStringIndirect, y: TypealiasNullableStringIndire // TESTCASE NUMBER: 13 fun case_13(x: otherpackage.Case13?) = - if ((x == null !is Boolean) !== true) { + if ((x == null !is Boolean) !== true) { throw Exception() } else { x @@ -204,18 +204,18 @@ fun case_14() { if (a.x != null == true) { if (a.x !== null == false) { if (a.x != null == null) { - if (a.x != null !== null) { - if (a.x != null === true) { - if (a.x !== null === true !is Boolean == true) { - if (a.x != null !== false) { - if (a.x != null === false) { - if (a.x !== null === true) { + if (a.x != null !== null) { + if (a.x != null === true) { + if (a.x !== null === true !is Boolean == true) { + if (a.x != null !== false) { + if (a.x != null === false) { + if (a.x !== null === true) { if ((a.x != null != true) !is Boolean) { if (a.x != null is Boolean) { if (a.x != null is Boolean is Boolean) { - if (a.x !== null is Boolean) { + if (a.x !== null is Boolean) { if (a.x != null is Boolean) { - if ((a.x !== null !is Boolean) == false) { + if ((a.x !== null !is Boolean) == false) { a.x a.x.equals(a.x) } @@ -238,7 +238,7 @@ fun case_14() { // TESTCASE NUMBER: 15 fun case_15(x: EmptyObject) { - val t = if (x === null is Boolean is Boolean is Boolean) "" else { + val t = if (x === null is Boolean is Boolean is Boolean) "" else { x x.equals(null) x.propT @@ -256,7 +256,7 @@ fun case_15(x: EmptyObject) { fun case_16() { val x: TypealiasNullableNothing = null - if (x != null !is Boolean !is Boolean !is Boolean !is Boolean !is Boolean) { + if (x != null !is Boolean !is Boolean !is Boolean !is Boolean !is Boolean) { x x.java } @@ -270,7 +270,7 @@ val case_17 = if (nullableIntPrope //TESTCASE NUMBER: 18 fun case_18(a: DeepObject.A.B.C.D.E.F.G.J?) { - if (a != null !== null) { + if (a != null !== null) { a a.equals(null) a.propT @@ -304,7 +304,7 @@ fun case_19(b: Boolean) { } } else null - if (a != null !is Boolean && a.B19 != null is Boolean && a.B19.C19 != null is Boolean && a.B19.C19.D19 != null == null && a.B19.C19.D19.x != null !== null) { + if (a != null !is Boolean && a.B19 != null is Boolean && a.B19.C19 != null is Boolean && a.B19.C19.D19 != null == null && a.B19.C19.D19.x != null !== null) { a.B19.C19.D19.x a.B19.C19.D19.x.equals(null) a.B19.C19.D19.x.propT @@ -330,7 +330,7 @@ fun case_20(b: Boolean) { } } - if (a.B19.C19.D19 !== null !is Boolean) { + if (a.B19.C19.D19 !== null !is Boolean) { a.B19.C19.D19 a.B19.C19.D19.equals(null) a.B19.C19.D19.propT @@ -346,7 +346,7 @@ fun case_20(b: Boolean) { // TESTCASE NUMBER: 21 fun case_21() { - if (EnumClassWithNullableProperty.B.prop_1 !== null is Boolean == true !is Boolean != true) { + if (EnumClassWithNullableProperty.B.prop_1 !== null is Boolean == true !is Boolean != true) { EnumClassWithNullableProperty.B.prop_1 EnumClassWithNullableProperty.B.prop_1.equals(null) EnumClassWithNullableProperty.B.prop_1.propT @@ -378,7 +378,7 @@ fun case_22(a: (() -> Unit)?) { // TESTCASE NUMBER: 23 fun case_23(a: ((Float) -> Int?)?, b: Float?) { - if (a != null !is Boolean && b !== null is Boolean) { + if (a != null !is Boolean && b !== null is Boolean) { val x = a(b) if (x != null) { x @@ -397,7 +397,7 @@ fun case_23(a: ((Float) -> Int?)?, b: Float?) { // TESTCASE NUMBER: 24 fun case_24(a: ((() -> Unit) -> Unit)?, b: (() -> Unit)?) = - if (a !== null is Boolean && b !== null !is Boolean) { + if (a !== null is Boolean && b !== null !is Boolean) { a(?")!>b) a(b) ?")!>b.equals(null) @@ -421,10 +421,10 @@ fun case_25(b: Boolean) { val y = if (b) x else null - if (y !== null === true) { + if (y !== null === true) { val z = ?")!>y() - if (z != null !== false) { + if (z != null !== false) { ? & ")!>z.a ? & ")!>z.a.equals(null) ? & ")!>z.a.propT @@ -443,7 +443,7 @@ fun case_25(b: Boolean) { fun case_26(a: ((Float) -> Int?)?, b: Float?) { if (a != null == true == false && b != null == true == false) { val x = a(b) - if (x != null == true === false) { + if (x != null == true === false) { x x.equals(null) x.propT diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/1.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/1.fir.kt index 08e77977663..9fab45fe097 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/1.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/1.fir.kt @@ -322,7 +322,7 @@ fun case_15(x: EmptyObject) { fun case_16() { val x: TypealiasNullableNothing = null - if (x != null) { + if (x != null) { x } } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/21.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/21.fir.kt index 61ad5574b16..b367166e0d3 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/21.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/21.fir.kt @@ -16,7 +16,7 @@ fun case_1(x: Any?) { * ISSUES: KT-28329 */ fun case_2(x: Any) { - if (x is Int === true) { + if (x is Int === true) { x x.inv() } @@ -60,7 +60,7 @@ fun case_6(x: Any?) { * ISSUES: KT-28329 */ fun case_7(x: Any) { - if (!(x is DeepObject.A.B.C.D.E.F.G.J) !== false) else { + if (!(x is DeepObject.A.B.C.D.E.F.G.J) !== false) else { x x.prop_1 } @@ -72,7 +72,7 @@ fun case_7(x: Any) { * ISSUES: KT-28329 */ fun case_8(x: Any?) { - if (!(x is Int?) !== false !== false !== false) else { + if (!(x is Int?) !== false !== false !== false) else { x x?.inv() } @@ -84,7 +84,7 @@ fun case_8(x: Any?) { * ISSUES: KT-28329 */ fun case_9(x: Any?) { - if (!!(x !is TypealiasNullableStringIndirect?) !== false === true) else { + if (!!(x !is TypealiasNullableStringIndirect?) !== false === true) else { x x?.get(0) } @@ -96,7 +96,7 @@ fun case_9(x: Any?) { * ISSUES: KT-28329 */ fun case_10(x: Any?) { - if (!!(x !is Interface3) === true && true) else { + if (!!(x !is Interface3) === true && true) else { x x.itest() x.itest3() diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/28.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/28.fir.kt index bffc15615b2..9e4b13388fe 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/28.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/28.fir.kt @@ -161,7 +161,7 @@ inline fun case_17(x: Any?) { * ISSUES: KT-30369, KT-28262, KT-29878 */ inline fun case_18(x: Any?) { - if (x?.equals(10) === null === true) else { + if (x?.equals(10) === null === true) else { x x.equals(10) } @@ -173,7 +173,7 @@ inline fun case_18(x: Any?) { * ISSUES: KT-30369, KT-28262, KT-29878 */ inline fun case_19(x: Any?) { - if (x?.equals(10) !== null === true) { + if (x?.equals(10) !== null === true) { x x.equals(10) } @@ -185,7 +185,7 @@ inline fun case_19(x: Any?) { * ISSUES: KT-30369, KT-28262, KT-29878 */ inline fun case_20(x: Any?) { - if (x?.equals(10) === null !== false) else { + if (x?.equals(10) === null !== false) else { x x.equals(10) } @@ -197,7 +197,7 @@ inline fun case_20(x: Any?) { * ISSUES: KT-30369, KT-28262, KT-29878 */ inline fun case_21(x: Any?) { - if (x?.equals(10) !== null !== false) { + if (x?.equals(10) !== null !== false) { x x.equals(10) } @@ -209,7 +209,7 @@ inline fun case_21(x: Any?) { * ISSUES: KT-30369, KT-28262, KT-29878 */ inline fun case_22(x: Any?) { - if (x?.equals(10) !== null !== true) else { + if (x?.equals(10) !== null !== true) else { x x.equals(10) } @@ -221,7 +221,7 @@ inline fun case_22(x: Any?) { * ISSUES: KT-30369, KT-28262, KT-29878 */ inline fun case_23(x: Any?) { - if (x?.equals(10) === null === false) { + if (x?.equals(10) === null === false) { x x.equals(10) } @@ -257,7 +257,7 @@ inline fun case_25(x: Any?) { * ISSUES: KT-30369, KT-29878 */ inline fun case_26(x: Any?) { - if (x?.equals(10) != null === false) else { + if (x?.equals(10) != null === false) else { x x.equals(10) } @@ -269,7 +269,7 @@ inline fun case_26(x: Any?) { * ISSUES: KT-30369, KT-29878 */ inline fun case_27(x: Any?) { - if (x?.equals(10) == null === false) { + if (x?.equals(10) == null === false) { x x.equals(10) } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/3.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/3.fir.kt index 4f0f679f4ce..f7a4d602e50 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/3.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/3.fir.kt @@ -181,7 +181,7 @@ fun case_15(x: TypealiasNullableString) { fun case_16() { val x: TypealiasNullableNothing = null - if (x == null || false || false || false) { + if (x == null || false || false || false) { x } } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/36.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/36.fir.kt index 4295b1f3bef..48479cd6a1e 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/36.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/36.fir.kt @@ -127,7 +127,7 @@ fun case_10(x: Any?, z: Any, b: Boolean?) { false -> return null -> throw Exception() } - z === y || if (b == true) return else if (b === false) null!! else throw Exception() + z === y || if (b == true) return else if (b === false) null!! else throw Exception() x y y.equals(10) @@ -137,7 +137,7 @@ fun case_10(x: Any?, z: Any, b: Boolean?) { fun case_11(x: Any?, z: Any, b: Boolean?) { while (true) { var y = x ?: if (b == true) continue!! else if (!(b != false)) return else break ?: break::class - z !== y && if (b == true) return else if (b === false) null!!else throw Exception() + z !== y && if (b == true) return else if (b === false) null!!else throw Exception() x y y.equals(10) @@ -148,7 +148,7 @@ fun case_11(x: Any?, z: Any, b: Boolean?) { fun case_12(x: Any?, z: Any, b: Boolean?) { while (true) { var y = select(x) ?: if (b == true) continue!! else if (!(b != false)) return else break ?: break::class - select(z) !== y && if (b == true) return else if (b === false) null!!else throw Exception() + select(z) !== y && if (b == true) return else if (b === false) null!!else throw Exception() x y y.equals(10) diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/37.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/37.fir.kt index 43ebaef81f5..52812f985a3 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/37.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/37.fir.kt @@ -77,7 +77,7 @@ fun case_6(x: Boolean?) { // TESTCASE NUMBER: 7 fun case_7(x: Boolean?) { while (true) { - if (!(x === false)) return + if (!(x === false)) return } x diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/4.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/4.fir.kt index 20b8b43935a..69beea19344 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/4.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/4.fir.kt @@ -257,7 +257,7 @@ fun case_22(a: (() -> Unit)) { fun case_23(a: ((Float) -> Int), b: Float) { if (a == null && b == null) { val x = a(b) - if (x !== null) { + if (x !== null) { x } } @@ -282,7 +282,7 @@ fun case_25(a: (() -> Unit) -> Unit, b: (() -> Unit) -> Unit = if (a === null) a else 0) { +fun case_26(a: Int, b: Int = if (a === null) a else 0) { a b } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/48.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/48.fir.kt index 34e123fd67c..1a57cdc8b1b 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/48.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/48.fir.kt @@ -21,7 +21,7 @@ fun case_1(x: Any?, y: Any?) { * ISSUES: KT-30317 */ fun case_2(x: Any?, y: Any?) { - if (x as Int === y) { + if (x as Int === y) { x x.inv(10) y @@ -49,7 +49,7 @@ fun case_3(x: Any?, y: Any?) { * ISSUES: KT-30317 */ fun case_4(x: Any?, y: Any?) { - if (y === x as Int) { + if (y === x as Int) { x x.inv(10) y diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/59.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/59.fir.kt index 38d0ea2640b..f672835e13e 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/59.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/59.fir.kt @@ -26,7 +26,7 @@ fun case_2() { do { x x = x.equals(10) - } while (x !== null) + } while (x !== null) } // TESTCASE NUMBER: 3 @@ -58,7 +58,7 @@ fun case_5() { do { x x = x.equals(10) - } while (x !== null) + } while (x !== null) } /* @@ -86,7 +86,7 @@ fun case_7() { do { x x = x.equals(10) - } while (x !== null) + } while (x !== null) } /* @@ -114,7 +114,7 @@ fun case_9() { do { x x = x.equals(10) - } while (x !== null) + } while (x !== null) } /* diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/6.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/6.fir.kt index 830e0be98e7..15917483423 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/6.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/6.fir.kt @@ -300,7 +300,7 @@ fun case_16() { val x: TypealiasNullableNothing = null val y: Nothing? = null - if (x !== y) { + if (x !== y) { x x.hashCode() } @@ -437,7 +437,7 @@ fun case_22(a: (() -> Unit)?) { // TESTCASE NUMBER: 23 fun case_23(a: ((Float) -> Int?)?, b: Float?, z: Nothing?) { - if (a != z && b !== z && b !== z) { + if (a != z && b !== z && b !== z) { val x = a(b) if (x != z || x !== implicitNullableNothingProperty) { x @@ -577,7 +577,7 @@ fun case_29(x: Boolean) { if (false || false || false || false || y !== v) { val t = ?")!>y() - if (z !== t || false) { + if (z !== t || false) { ?")!>t.a ?")!>t.equals(null) ?")!>t.propT @@ -677,7 +677,7 @@ fun case_33(a: ((Float) -> Int?)?, b: Float?, c: Boolean?) { fun case_34(z1: Boolean?) { var z = null - if (true && true && true && true && EnumClassWithNullableProperty.A.prop_1 != implicitNullableNothingProperty && EnumClassWithNullableProperty.A.prop_1 !== null && EnumClassWithNullableProperty.A.prop_1 !== z || z1 != implicitNullableNothingProperty || z1!! && true && true) { + if (true && true && true && true && EnumClassWithNullableProperty.A.prop_1 != implicitNullableNothingProperty && EnumClassWithNullableProperty.A.prop_1 !== null && EnumClassWithNullableProperty.A.prop_1 !== z || z1 != implicitNullableNothingProperty || z1!! && true && true) { } else { EnumClassWithNullableProperty.A.prop_1 @@ -910,7 +910,7 @@ fun case_51() { val x: TypealiasNullableNothing = null val z: Nothing? = null - if (x === z || z == x && x == z || false || false || false) { + if (x === z || z == x && x == z || false || false || false) { x x.hashCode() } @@ -1401,7 +1401,7 @@ fun case_75(t: Any?, z: Nothing?) { } // TESTCASE NUMBER: 76 -fun case_76(a: Any?, b: Int = if (a !is Number? === true || a !is Int? == true || a != null == false == true) 0 else a) { +fun case_76(a: Any?, b: Int = if (a !is Number? === true || a !is Int? == true || a != null == false == true) 0 else a) { a b b.equals(null) diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/7.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/7.fir.kt index 1c46970b55b..db0427a20fb 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/7.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/7.fir.kt @@ -168,7 +168,7 @@ fun case_9(x: TypealiasNullableString?) { fun case_10() { val a = Class() - if (a.prop_4 === null || a.prop_4 === null || true) { + if (a.prop_4 === null || a.prop_4 === null || true) { if (a.prop_4 != null) { a.prop_4 a.prop_4.equals(null) @@ -283,14 +283,14 @@ fun case_16() { val x: TypealiasNothing? = null val y: Nothing? = null - if (x != null || x !== null || x != y) { + if (x != null || x !== null || x != y) { x x.hashCode() } } // TESTCASE NUMBER: 17 -val case_17 = if (nullableIntProperty == null || nullableNothingProperty === nullableIntProperty) 0 else { +val case_17 = if (nullableIntProperty == null || nullableNothingProperty === nullableIntProperty) 0 else { nullableIntProperty.equals(null) nullableIntProperty.propT nullableIntProperty.propAny diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index f1fc3d139f5..0ce223bebb6 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -307,6 +307,10 @@ enum class LanguageFeature( // When this feature is enabled, no such errors are reported. NoBuilderInferenceWithoutAnnotationRestriction(sinceVersion = null, kind = OTHER), + // Disabled for indefinite time. Forces K2 report errors (instead of warnings) for incompatible + // equality & identity operators in cases where K1 would report warnings or would not report anything. + ReportErrorsForComparisonOperators(sinceVersion = null, kind = BUG_FIX), + // Experimental features BreakContinueInInlineLambdas(null), // KT-1436